Large factorial using BigIntegers losing precision - c#

It'sa me, with another problem.
I need to calculate a factorial of a really huge number, lets assume it is 95.
So as we all know 95! equals to:
10329978488239062144133688859495761720042551046933218543167809699858950620982142410696539365993509132394773015016946331626553858953528454377577119744
I have used a simple method calculating factorials using BigIntegers that I found somewhere around here few months ago:
public static BigInteger FactorialTest(BigInteger x)
{
if (x == 0)
return 1;
BigInteger res = x;
x--;
while (x > 1)
{
res *= x;
x--;
}
return res;
}
And only got a rounded up number:
10329978488239059262599702099394727095397746340117372869212250571234293987594703124871765375385424468563282236864226607350415360000000000000000000000
Next step was using the builtin BigInteger methods for addition, multiplication etc, hoping it will fix the problem - no still did not work.
Last thing I tried was using code of someone smarter, so reached for SolverFoundation, unfortunately
Microsoft.SolverFoundation.Common.BigInteger.Factorial(95)
still returns the rounded up number.
Is there anything I am missing that could get me the proper result? I really hoped BigIntegers would not lose precision like that.

According to http://2000clicks.com/MathHelp/BasicFactorialTable.aspx and other sites the number you are getting from your calculation is correct.

Related

c# - What does binary representation of uint is like?

I'm trying to solve a simple question on leetcode.com (https://leetcode.com/problems/number-of-1-bits/) and I encounter a strange behavior which is probably my lack of understanding...
My solution to the question in the link is the following:
public int HammingWeight(uint n) {
int sum = 0;
while (n > 0) {
uint t = n % 10;
sum += t == 0 ? 0 : 1;
n /= 10;
}
return sum;
}
My solution was to isolate each number and if it's one increase the sum. When I ran this on my PC it worked (yes - I know it's not the optimal solution and there are more elegant solutions considering it's binary representation).
But when I tried running in the leetcode editor it returned a wrong answer for the following input (00000000000000000000000000001011).
No real easy way to debug other then printing to the console so I printed the value of n when entering the method and got the result of 11 instead of 1011 - on my PC I got 11. If I take a different solution - one that uses bitwise right shift or calculating mod by 2 then it works even when the printed n is still 11. And I would have expected those solutions to fail as well considering that n is "wrong" (different from my PC and the site as described).
Am I missing some knowledge regarding the representation of uint? Or binary number in a uint variable?
Your code appears to be processing it as base 10 (decimal), but hamming weight is about base 2 (i.e. binary). So: instead if doing % 10 and /= 10, you should be looking at % 2 and /= 2.
As for what uint looks like as binary: essentially like this, but ... the CPU is allowed to lie about where each of the octets actually is (aka "endianness"). The good news is: it doesn't usually expose that lie to you unless you cheat and look under the covers by looking at raw memory. As long as you use regular operators (include bitwise operators): the lie will remain undiscovered.
Side note: for binary work that is about checking a bit and shuffling the data down, & 1 and >> 1 would usually be preferable to % 2 and / 2. But as canton7 notes: there are also inbuilt operations for this specific scenario which uses the CPU intrinsic instruction when possible (however: using the built-in function doesn't help you increase your understanding!).
This Kata has a poor writing, in the examples the Inputs are printed in binary representation while the Outputs are in printed in decimal representation. And there is no clues to help understand that.
00000000000000000000000000001011b is 11 (in decimal, 8 + 2 + 1). That is why you get 11 as input for the first test case.
There is no numbers made of 0s and 1s in base 10 you have to decode as base 2 stuff here.
To solve the Kata, you just need to work in base 2 as you succeed to do and like #MarcGravell explained.
Please check below code, it will work for you.
Its very simple way to solve.
var result = 0;
for(var i = 0; i < 32; i++)
{
if ((n & 1) == 1) result++;
n = n >> 1;
}
return result;

A Solution for Returning Derivative = Infinity

This is a Math question, but to try to solve a C# Programming issue so I am not sure if here is the best place for it.
In the following code, I can get the Derivative:
var x = 13.399E+153;
var d = ((1 + x) * (1 - x));
Console.WriteLine("d = {0:0}", d);
Console.ReadLine();
Where 13.399E+153; the 9's are recurring. But if x becomes:
var x = 14.00E+153;
I get -Infinity. I have done some research already but do not understand any possible solution.
URL: Mathematical function differentiation with C#?
also: Limit of the derivative of a function as x goes to infinity
I do understand why this is ocurring however:
If the limit of f(x) f(x) exists, there is a horizontal asymptote.
Therefore as the function approaches infinity it becomes more linear and
...thus the derivative approaches zero.
.
My question is, if I am returning the Derivative as a double for example, what would a solution be to prevent it being returned as Infinity? Should I return 1, or Zero?
if (double.IsInfinity(Derivative))
{
return ?;
}
You get the result of negative Infinity because the mathematical value of the result is less than the least value that can be represented using 64 bit floating point numbers. This is completely normal, I see nothing that needs to be fixed.

Trouble raising -1 to a rational fraction-based power

On my TI-84 Plus (Silver Edition), I can enter the following without error: (-1)^(1/3) = -1
I also know that entering some expressions like the following would yield a non-real -imaginary- number like: (-1)^.5
Now, my problem is with C#'s Math object. If I send any fractions like these: {1.667, 109.667, 0.667, 120.667} OR {4/3, 111/3, 2/3, 122/3}, I would get: {NaN, NaN, NaN, NaN}.
Do I have to write a new object MathHelper that checks the rational value and returns an answer according to a limited input switch? Or is there a feature to the Math object I am missing. I can do this on the calculator...
PS, I did not come across any similar questions online yet; so if this is a duplicate, please inform me ;)
[My new views]
Thank you all for your help! I had finished upgrading the "Microsoft.Solver.Foundation.dll" to the 4.0 targeted framework and it turned out that the 'Rational' object seemed to return only -1's and 'Indeterminate'. Then after entering (-1)^(1/2) [nonreal ans] on Google, it dawned on me that I was working with nth-roots!! So, it turned out that I had already managed imaginary numbers in the past in C#, hence having solved my problem:
Any even root 2n of a negative number -m will always equal an imaginary number i. (2n√-m)=i
I can't believe I forgot this simple algebra property
You will have to write your own Math helper to do functions like this (at least for Math.Pow). EDIT: Or you can use the Rational library like mentioned in the comments.
According to the documentation:
Input: x < 0 but not NegativeInfinity; y is not an integer, NegativeInfinity, or PositiveInfinity.
Result: NaN
Review the docs here: http://msdn.microsoft.com/en-us/library/system.math.pow.aspx
In C#, (-1)^R isn't defined for non-integer values of R.
If you try to calculate (-1)^(1/3), C# will calculate 1/3 first, resulting in a non-integer floating point number for R.
Solution:
Use the mathematical identity:
a^(x/y) = a^x * a^(1/y) x,y integers
For negative a, use:
a^1/y = -(|a|^1/y) // only works if y is odd
Or put together:
if (a < 0) {
if (y % 2 = 1) {
result = a^x * -1 * (-a)^(1.0/y); // Replace ^ with the correct C# call.
} else {
// NaN
}
} else {
result = a^(x/y);
}

C# isPowerOf function

I have the next function:
static bool isPowerOf(int num, int power)
{
double b = 1.0 / power;
double a = Math.Pow(num, b);
Console.WriteLine(a);
return a == (int)a;
}
I inserted the print function for analysis.
If I call the function:
isPowerOf(25, 2)
It return true since 5^2 equals 25.
But, if I call 16807, which is 7^5, the next way:
isPowerOf(16807, 5)
In this case, it prints '7' but a == (int)a return false.
Can you help? Thanks!
Try using a small epsilon for rounding errors:
return Math.Abs(a - (int)a) < 0.0001;
As harold suggested, it will be better to round in case a happens to be slightly smaller than the integer value, like 3.99999:
return Math.Abs(a - Math.Round(a)) < 0.0001;
Comparisons that fix the issue have been suggested, but what's actually the problem here is that floating point should not be involved at all. You want an exact answer to a question involving integers, not an approximation of calculations done on inherently inaccurate measurements.
So how else can this be done?
The first thing that comes to mind is a cheat:
double guess = Math.Pow(num, 1.0 / power);
return num == exponentiateBySquaring((int)guess, power) ||
num == exponentiateBySquaring((int)Math.Ceil(guess), power);
// do NOT replace exponentiateBySquaring with Math.Pow
It'll work as long as the guess is less than 1 off. But I can't guarantee that it will always work for your inputs, because that condition is not always met.
So here's the next thing that comes to mind: a binary search (the variant where you search for the upper boundary first) for the base in exponentiateBySquaring(base, power) for which the result is closest to num. If and only if the closest answer is equal to num (and they are both integers, so this comparison is clean), then num is a power-th power. Unless there is overflow (there shouldn't be), that should always work.
Math.Pow operates on doubles, so rounding errors come into play when taking roots. If you want to check that you've found an exact power:
perform the Math.Pow as currently, to extract the root
round the result to the nearest integer
raise this integer to the supplied power, and check you get the supplied target. Math.Pow will be exact for numbers in the range of int when raising to integer powers
If you debug the code and then you can see that in first comparison:
isPowerOf(25, 2)
a is holding 5.0
Here 5.0 == 5 => that is why you get true
and in 2nd isPowerOf(16807, 5)
a is holding 7.0000000000000009
and since 7.0000000000000009 != 7 => you are getting false. and Console.WriteLine(a) is truncating/rounding the double and only show 7
That is why you need to compare the nearest value like in Dani's solution

factorial method resulting in error

I'm trying to get the factorial value of number 66, but my method resulting me an output 0. But whenever I try to get the factorial of 5, it is resulting me an output 120. Could anyone please tell me why?
public static int factorial(int n)
{
if (n == 1)
return n;
return n * factorial(n - 1);
}
Sure - factorials get very big, very fast. You're overflowing the bounds of int very quickly... and at some point you'll have multiplied by enough factors to get an overflow to 0, which will then keep the value at 0 forever.
According to a quick Google search, 66 factorial is 5.44344939 × 1092 - which is considerably more than int can handle, or even long or decimal. You could get double to handle it - you'd lose a huge amount of precision, and that would accumulate really quickly too, but at least it wouldn't overflow...
Your method overflows. See the following example:
static void Main(string[] args)
{
Console.WriteLine(factorial(66));
}
public static int factorial(int n)
{
if (n == 1)
return n;
var result = n * factorial(n - 1);
Console.WriteLine("{0} : {1}", n, result);
return result;
}
With this example, the results of each iteration is printed.
You see that at one point, result becomes 0 and this means that every iteration from that point on becomes n * 0.
You can try using BigInteger. This will give the correct result. Calculate factorials in C# contains more information on this.
66! does not fit into an int. Use BigInteger.
The problem is that the factorial of 66 is way to large to fit into an int. I think it will also we way to large to fit into a long.
As an example, factorial(20) will return 2432902008176640000
The factorial of 50 is 3.0414093202×1064 which exeeds already what a int can contain.
Use long or BigInteger for this.
You get numeric overflow, 66! ~= 5e92 which is way larger than an int can handle. Also, factorials are better calculated using a for loop.
Approximately 13 or 14 is the largest number whose factorial fits in an int... If you switch to long, it'll be aroung 18 or 19 if I recall correctly. If you wish arbitraty big numbers you'd have to write your own big arithmetic library or use an existing one :)
You need to use the appropriate data type.
In this case the Big Integer data type is probably best seeing as how fast the numbers get real big.
Here is the way you use this data type.
Right click on your project, choose the add reference menu.
Look for the system.numerics library and add it.
You then add the using clause in your code.
And then you can initialise variable with the keyword as usual.

Categories

Resources