I'm trying to calculate a large number, which requires BigInteger.Pow(), but I need the exponent to also be a BigInteger and not int.
i.e.
BigInteger.Pow(BigInteger)
How can I achieve this?
EDIT: I came up with an answer. User dog helped me to achieve this.
public BigInteger Pow(BigInteger value, BigInteger exponent)
{
BigInteger originalValue = value;
while (exponent-- > 1)
value = BigInteger.Multiply(value, originalValue);
return value;
}
Just from the aspect of general maths, this doesn't make sense. That's why it's not implemented.
Think of this example: Your BigInteger number is 2 and you need to potentiate it by 1024. This means that the result is a 1 KB number (2^1024). Now imagine you take int.MaxValue: Then, your number will consume 2 GB of memory already. Using a BigInteger as an exponent would yield a number beyond memory capacity!
If your application requires numbers in this scale, where the number itself is too large for your memory, you probably want a solution that stores the number and the exponent separately, but that's something I can only speculate about since it's not part of your question.
If your your issue is that your exponent variable is a BigInteger, you can just cast it to int:
BigInteger.Pow(bigInteger, (int)exponent); // exponent is BigInteger
Pow(2, int64.MaxValue) requires 1,152,921 terabytes just to hold the number, for a sense of scale. But here's the function anyways, in case you have a really nice computer.
static BigInteger Pow(BigInteger a, BigInteger b) {
BigInteger total = 1;
while (b > int.MaxValue) {
b -= int.MaxValue ;
total = total * BigInteger.Pow(a, int.MaxValue);
}
total = total * BigInteger.Pow(a, (int)b);
return total;
}
As others have pointed out, raising something to a power higher than the capacity of int is bad news. However, assuming you're aware of this and are just being given your exponent in the form of a BigInteger, you can just cast to an int and proceed on your merry way:
BigInteger.Pow(myBigInt, (int)myExponent);
or, even better,
try
{
BigInteger.Pow(myBigInt, (int)myExponent);
}
catch (OverflowException)
{
// Do error handling and stuff.
}
For me the solution was to use the function BigInteger.ModPow(BigInteger value, BigInteger exponent, BigInteger modulus) because I needed to do a mod afterwards anyway.
The function calculates a given BigInteger to the power of another BigInteger and calculates the modulo with a third BitInteger.
Although it will still take a good amount of CPU Power it can be evaluated because the function already knows about the modulo and therefore can save a ton of memory.
Hope this might help some with the same question.
Edit:
Is available since .Net Framework 4.0 and is in .Net Standard 1.1 and upwards.
I came up with:
public BigInteger Pow(BigInteger value, BigInteger exponent)
{
BigInteger originalValue = value;
while (exponent-- > 1)
value = BigInteger.Multiply(value, originalValue);
return value;
}
Related
Before you read, please be aware that I'm aware of the differences between integer and floating-point division, and I'm aware of how BigInteger.DivRem and BigInteger.Divide.
Consider the following code examples:
BigInteger a = new(5);
BigInteger b = new(2);
BigInteger div = BigInteger.DivRem(a, b, out BigInteger rem);
Console.WriteLine($"{div}.{rem}");
Output = 2.1
BigInteger a = new(5678);
BigInteger b = new(1234);
BigInteger div = BigInteger.DivRem(a, b, out BigInteger rem);
Console.WriteLine($"{div}.{rem}");
Output = 4.742
Neither of the outputs is correct (in the context of what I'm asking). Sure, they're correct in the sense that they're displaying a division and a remainder formatted as ${div}.{rem}, but in my case, that's not what I'm looking for.
The correct values would be 2.5 and 4.6012965964 (with a scale of 10 digits) respectively.
Is there a way to convert/represent the remainder as a fractional value, rather than as a remainder?
Note: I know there is float, double and decimal, but those aren't the solution I'm looking for.
This seems to work:
BigInteger a = new(5678);
BigInteger b = new(1234);
BigInteger div = BigInteger.DivRem(a, b, out BigInteger rem);
var decimalDigits = new List<BigInteger>();
while (rem != 0 && decimalDigits.Count < 10)
{
rem *= 10;
decimalDigits.Add(BigInteger.DivRem(rem, b, out rem));
}
Console.WriteLine($"{div}.{string.Concat(decimalDigits)}");
This is pretty much just an implementation of long division.
You have misunderstood - what you are doing is integer arithmetic on big integers and the results are correct. Read here Math.DivRem() (to understand DIV and REM as concepts, forget about integral type for now).
What you seem to be after is a floating point type with precision greater than double. Last time I looked no such type exists in .Net, except for a few privateer efforts like QPFloat
How can I ensure that when changing a bit from a BitArray, the BitArray value remains in a range.
Example:
Given the range [-5.12, 5.12] and
a = 0100000000000000011000100100110111010010111100011010100111111100 ( = 2.048)
By changing a bit at a random position, I need to ensure that the new value remains in the given range.
I'm not 100% sure what you are doing and this answer assumes you are storing a as a 64-bit value (long) currently. The following code may help point you in the right direction.
const double minValue = -5.12;
const double maxValue = 5.12;
var initialValue = Convert.ToInt64("100000000000000011000100100110111010010111100011010100111111100", 2);
var changedValue = ChangeRandomBit(initialValue); // However you're doing this
var changedValueAsDouble = BitConverter.Int64BitsToDouble(initialValue);
if ((changedValueAsDouble < minValue) || (changedValueAsDouble > maxValue))
{
// Do something
}
It looks like double (64 bits and result has decimal point).
As you may know it has sign bit, exponent and fraction, so you can not change random bit and still have value in the range, with some exceptions:
sign bit can be changed without problem if your range is [-x;+x] (same x);
changing exponent or fraction will require to check new value range but:
changing exponent of fraction bit from 1 to 0 will make |a| less.
I don't know what you are trying to achieve, care to share? Perhaps you are trying to validate or correct something, then you may have a look at this.
Here's an extension method that undoes the set bit if the new value of the float is outside the given range (this is an example only, it relies on the BitArray holding a float with no checks, which is pretty horrible so just hack a solution out of this, incl changing to double):
static class Extension
{
public static void SetFloat(this BitArray array, int index, bool value, float min, float max)
{
bool old = array.Get(index);
array.Set(index, value);
byte[] bytes = new byte[4];
array.CopyTo(bytes, 0);
float f = BitConverter.ToSingle(bytes, 0);
if (f < min || f > max)
array.Set(index, old);
}
}
Example use:
static void Main(string[] args)
{
float f = 2.1f;
byte[] bytes = System.BitConverter.GetBytes(f);
BitArray array = new BitArray(bytes);
array.Set(20, true, -5.12f, 5.12f);
}
If you can actually limit your precision, then this would be a lot easier. For example given the range:
[-5.12, 5.12]
If I multiply 5.12 by 100, I get
[-512, 512]
And the integer 512 in binary is, of course:
1000000000
So now you know you can set any of the first 9 bits and you'll be < 512 if the 10th bit is 0. If you set the 10th bit, you will have to set all the other bits to 0. With a little extra effort, this can be extended to deal with 2's complement negative values too (although, I might be inclined just to convert them to positive values)
Now if you actually need to accommodate the 3 d.p. of 2.048, then you'll need to multiply all you values by 1000 instead and it will be a little more difficult because 5120 in binary is 1010000000000
You know you can do anything you want with everything except the most significant bit (MSB) if the MSB is 0. In this case, if the MSB is 1, but the next 2 bits are 0, you can do anything you want with the remaining bits.
The logic involved with dealing directly with the number in IEEE-754 floating point format is probably going to be torturous.
Or you could just go with the "mutate the value and then test it" approach, if it's out-of-range, go back and try again. Which might be suitable (in practice), but won't be guaranteed to exit.
A final thought, depending on exactly what you are doing, you might want to also look at Gray Codes. The idea of a Gray Code is to make it such that each value is only 1 bit flip apart. With naturally encoded binary, a flip of the MSB has orders of magnitude more impact on the final value than a flip of the LSB.
I have a method that converts value to a newBase number of length length.
The logic in english is:
If we calculated every possible combination of numbers from 0 to (c-1)
with a length of x
what set would occur at point i
While the method below does work perfectly, because very large numbers are used, it can take a long time to complete:
For example, value=(((65536^480000)-1)/2), newbase=(65536), length=(480000) takes about an hour to complete on a 64 bit architecture, quad core PC).
private int[] GetValues(BigInteger value, int newBase, int length)
{
Stack<int> result = new Stack<int>();
while (value > 0)
{
result.Push((int)(value % newBase));
if (value < newBase)
value = 0;
else
value = value / newBase;
}
for (var i = result.Count; i < length; i++)
{
result.Push(0);
}
return result.ToArray();
}
My question is, how can I change this method into something that will allow multiple threads to work out part of the number?
I am working C#, but if you're not familiar with that then pseudocode is fine too.
Note: The method is from this question: Cartesian product subset returning set of mostly 0
If that GetValues method is really the bottleneck, there are several things you can do to speed it up.
First, you're dividing by newBase every time through the loop. Since newBase is an int, and the BigInteger divide method divides by a BigInteger, you're potentially incurring the cost of an int-to-BigInteger conversion on every iteration. You might consider:
BigInteger bigNewBase = newBase;
Also, you can cut the number of divides in half by calling DivRem:
while (value > 0)
{
BigInteger rem;
value = BigInteger.DivRem(value, bigNewBase, out rem);
result.Push((int)rem);
}
One other optimization, as somebody mentioned in comments, would be to store the digits in a pre-allocated array. You'll have to call Array.Reverse to get them in the proper order, but that takes approximately no time.
That method, by the way, doesn't lend itself to parallelizing because computing each digit depends on the computation of the previous digit.
So I'm attempting to use the Newton-Raphson method to find the square root of a BigInteger.
Here is my code:
private void sqrRt(BigInteger candidate)
{
BigInteger epsilon = new BigInteger(0.0001);
BigInteger guess = candidate / 2;
while (BigInteger.Abs(guess * guess - candidate) >= epsilon)
{
// guess = guess - (((guess**2) - y)/(2*guess))
guess = BigInteger.Subtract(guess, BigInteger.Divide(BigInteger.Subtract(BigInteger.Multiply(guess, guess), candidate), BigInteger.Multiply(2, guess)));
MessageBox.Show(Convert.ToString(guess));
}
}
The problem seems to be that the BigInteger is not precise enough to fall within the degree of accuracy of the epsilon in the while loop - i.e. it needs a decimal place. My question is what/how/where do I convert to a double to make the while loop eventually return false?
You are using the wrong data type. In order to have decimal points, you would need to use double, float, decimal, or Complex.
Check the links of all these types so you can see their digits of precision.
I'm messing around with writing a class similar to mpz (C) or BigInteger (Java). This is just for fun, so please don't go on about how I shouldn't be writing my own.
I have a class similar to:
public class HugeInt
{
public List<Integer> digits;
public HugeInt(String value)
{
// convert string value into its seperate digits.
// store them in instance variable above
}
}
Now, doing the add() and subtract() method of this class are pretty simple. Here is an example:
private List<Integer> add(List<Integer> a, List<Integer> b)
{
List<Integer> smallerDigits = (compareDigits(a,b) < 0) ? a : b;
List<Integer> largerDigits = (compareDigits(a,b) >= 0) ? a : b;
List<Integer> result = new ArrayList<Integer>();
int carry = 0;
for(int i = 0; i < largerDigits.size(); i++)
{
int num1 = largerDigits.get(i);
int num2 = (i < smallerDigits.size()) ? smallerDigits.get(i) : 0;
result.add((num1 + num2 + carry) % 10);
carry = ((num1 + num2 + carry) / 10);
}
if (carry != 0) result.add(carry);
return result;
}
Similarly, doing the multiply wasn't that hard either.
I see on wikipedia there is a page on Division Algorithms, but I'm not sure which one is appropriate for what I'm trying to do.
Because these positive integers (represented as digits) can be arbitrarily long, I want to make sure I don't attempt to do any operations on anything other than digit-by-digit basis.
However, can anyone point me in the right direction for doing a division of two numbers that are represented as List<Integer>'s? Also, I can ignore the remainder as this is integer division.
You could just do long division, but this certainly isn't the optimal way to do it (edit: although it seems that something like this is a good way to do it). You could look at other implementations of big integer libraries, and a bit of Googling turns up a fair bit of useful information.
This may be a slight overkill, but if this is the kind of things you do for fun, you'll enjoy reading this:
http://www.fizyka.umk.pl/nrbook/c20-6.pdf
(that's "Arithmetic at Arbitrary Precision" from "Numerical recipes in C").
Pretty fascinating, as is most of this book, with good explanations and lots of code.
Since I assume you're just dealing with integer division it's not very hard. Multiplication is repeated addition, division is the opposite - repeated subtraction. So what you'll do is check how many times you can subtract the divisor from the dividend. For example, 3 can be subtracted from 10 3 times without going <0, so the integer division quotient is 3.
This article A Larger Integer does not show how to implement digit by digit operations for "larger integers", but it does show how to implement a (apparently fully functional) 128 bit integer in terms of two Int64 types. I would imagine that it would not be too hard to extend the approach to use an array of Int64 types to yield an arbitary length integer. I just spent a few minutes looking back over the article and the implementation of multiply looks like it could get pretty involved for arbitrary length.
The article shows how to implement division (quotient and remainder) using binary division.