Factorial loop becomes 0
Starting from 34!, all factorials are divisible by 2^32. So when your computer program computes the results modulo 2^32 (which, although you don't say what programming language you're using, this is likely), then the results are always 0.
Here is a program that computes factorials mod 2^32 in Python:
def sint(r):
r %= (1 << 32)
return r if r < (1 << 31) else r - (1 << 32)
r = 1
for i in xrange(1, 40):
r *= i
print '%d! = %d mod 2^32' % (i, sint(r))
Which gives this output, which agrees with the output from your own program:
1! = 1 mod 2^32
2! = 2 mod 2^32
3! = 6 mod 2^32
4! = 24 mod 2^32
5! = 120 mod 2^32
6! = 720 mod 2^32
7! = 5040 mod 2^32
8! = 40320 mod 2^32
9! = 362880 mod 2^32
10! = 3628800 mod 2^32
11! = 39916800 mod 2^32
12! = 479001600 mod 2^32
13! = 1932053504 mod 2^32
14! = 1278945280 mod 2^32
15! = 2004310016 mod 2^32
16! = 2004189184 mod 2^32
17! = -288522240 mod 2^32
18! = -898433024 mod 2^32
19! = 109641728 mod 2^32
20! = -2102132736 mod 2^32
21! = -1195114496 mod 2^32
22! = -522715136 mod 2^32
23! = 862453760 mod 2^32
24! = -775946240 mod 2^32
25! = 2076180480 mod 2^32
26! = -1853882368 mod 2^32
27! = 1484783616 mod 2^32
28! = -1375731712 mod 2^32
29! = -1241513984 mod 2^32
30! = 1409286144 mod 2^32
31! = 738197504 mod 2^32
32! = -2147483648 mod 2^32
33! = -2147483648 mod 2^32
34! = 0 mod 2^32
35! = 0 mod 2^32
36! = 0 mod 2^32
37! = 0 mod 2^32
38! = 0 mod 2^32
39! = 0 mod 2^32
And here's a table of the exact values of this range of factorials, showing how many powers of 2 each contains:
1! = 1. Divisible by 2^0
2! = 2. Divisible by 2^1
3! = 6. Divisible by 2^1
4! = 24. Divisible by 2^3
5! = 120. Divisible by 2^3
6! = 720. Divisible by 2^4
7! = 5040. Divisible by 2^4
8! = 40320. Divisible by 2^7
9! = 362880. Divisible by 2^7
10! = 3628800. Divisible by 2^8
11! = 39916800. Divisible by 2^8
12! = 479001600. Divisible by 2^10
13! = 6227020800. Divisible by 2^10
14! = 87178291200. Divisible by 2^11
15! = 1307674368000. Divisible by 2^11
16! = 20922789888000. Divisible by 2^15
17! = 355687428096000. Divisible by 2^15
18! = 6402373705728000. Divisible by 2^16
19! = 121645100408832000. Divisible by 2^16
20! = 2432902008176640000. Divisible by 2^18
21! = 51090942171709440000. Divisible by 2^18
22! = 1124000727777607680000. Divisible by 2^19
23! = 25852016738884976640000. Divisible by 2^19
24! = 620448401733239439360000. Divisible by 2^22
25! = 15511210043330985984000000. Divisible by 2^22
26! = 403291461126605635584000000. Divisible by 2^23
27! = 10888869450418352160768000000. Divisible by 2^23
28! = 304888344611713860501504000000. Divisible by 2^25
29! = 8841761993739701954543616000000. Divisible by 2^25
30! = 265252859812191058636308480000000. Divisible by 2^26
31! = 8222838654177922817725562880000000. Divisible by 2^26
32! = 263130836933693530167218012160000000. Divisible by 2^31
33! = 8683317618811886495518194401280000000. Divisible by 2^31
34! = 295232799039604140847618609643520000000. Divisible by 2^32
35! = 10333147966386144929666651337523200000000. Divisible by 2^32
36! = 371993326789901217467999448150835200000000. Divisible by 2^34
37! = 13763753091226345046315979581580902400000000. Divisible by 2^34
38! = 523022617466601111760007224100074291200000000. Divisible by 2^35
39! = 20397882081197443358640281739902897356800000000. Divisible by 2^35
For loop in c# vs For loop in python
What you're likely running into here is integer overflow with the C# version of the Factorial function (at least your implementation of it, or wherever its coming from).
In C#, an int
is a numerical type stored in 32 bits of memory, which means it's bounded by -2^31 <= n <= 2^31 - 1
which is around +/- 2.1 billion. You could try using a long
type, which is a 64 bit numerical type, however for even larger upper bounds in your for loop, like getting close to 100, you're going to overflow long
as well.
When you run the Factorial function in C#, it starts off normally for the first little while, however if you keep going, you'll see that it all of a sudden jumps into negative numbers, and if you keep going even further than that, it'll get to 0 and stop changing. You're seeing the output of infinity due to division by 0, and C# has a way of handling that with doubles; that being to just return double.PositiveInfinity
.
The reason why this doesn't happen in python is that it uses a variable number of bits to store its numerical values.
Added note: What you might also want to try is using a Factorial function that works with the double
type instead of int
or long
, however by doing this, you'll lose precision on what the exact value is, but you get more range as the magnitude of the number you can store is larger
Further Note: As mentioned in the comments, C# has a type called BigInteger
which is designed to handle huge numbers like the values you would expect from large inputs to a Factorial function. You can find a reference to the BigInteger docs here
What you can do is calculate each component of the factorial function separately with the power you're using. Here's what I mean:
public decimal Exp(decimal power, int accuracy = 100)
{
decimal runningTotal = 1;
decimal finalValue = 1;
for (int i = 1; i <= accuracy; i++)
{
runningTotal *= power/i;
finalValue += runningTotal;
}
return finalValue;
}
Calculating Factorials in C# - No Errors, But Doesn't Work?
It's always the simple things that get us.
In your loop you have this:
for (int i = 1; 1 <= userNumber; i++)
I believe you mean this:
for (int i = 1; i <= userNumber; i++)
In the conditional part of the loop you used a '1' rather than 'i'.
Here's a program to find the factorial of a number. Why am I getting 0 as the answer? Which datatype should I use instead?
33!
is actually way out of the range of a 32 bit int
, whether signed or unsigned. 12!
has a value of 479001600, while 13!
has a value of 6227020800
, so you go out of range at 13!
.
Note also that result
is defined as an int
and you return an int
from fact
. This means you end up with signed integer overflow which invokes undefined behavior. This can be fixed by changing the type of both to unsigned
, although you're still limited to 12!
.
You can try using unsigned long long
for your types instead. That will get you up to 20!
. If you want values larger than that, you need to use a bigint library such as GMP.
Why Is This Factorial Algorithm Not Accurate
Someone posted a similar question a while back. The consensus was if you're writing it for work use a big number library (like GMP) and if it's a programming exercise write up a solution using a character array.
For example:
/* fact50.c
calculate a table of factorials from 0! to 50! by keeping a running sum of character digits
*/
#include <stdio.h>
#include <string.h>
int main (void)
{
printf ("\n Table of Factorials\n\n");
// length of arrays = 65 character digits
char str[] =
"00000000000000000000000000000000000000000000000000000000000000000";
char sum[] =
"00000000000000000000000000000000000000000000000000000000000000001";
const int len = strlen (str);
int index;
for ( int i = 0; i <= 50; ++i ) {
memcpy (str, sum, len);
for ( int j = 1; j <= i - 1; ++j ) {
index = len - 1;
int carry = 0;
do {
int digit = (sum[index] - '0') + (str[index] - '0') + carry;
carry = 0;
if ( digit > 9 ) {
carry = 1;
digit %= 10;
}
sum[index] = digit + '0';
--index;
}
while ( index >= 0 );
}
printf ("%2i! = ", i);
for ( index = 0; sum[index] == '0'; ++index )
printf ("%c", '.');
for ( ; index < len; ++index )
printf ("%c", sum[index]);
printf ("\n");
}
return 0;
}
Calculate factorials in C#
Have a look at the BigInteger
structure:
http://msdn.microsoft.com/en-us/library/system.numerics.biginteger.aspx
Maybe this can help you implement this functionality.
CodeProject has an implementation for older versions of the framework at http://www.codeproject.com/KB/cs/biginteger.aspx.
Related Topics
Login Using Google Oauth 2.0 with C#
Why Does Environment.Exit() Not Terminate the Program Any More
Cookie Confusion with Formsauthentication.Setauthcookie() Method
How to Add Event Handler for Dynamically Created Controls at Runtime
How to Connect to a Usb Webcam in .Net
Do Interfaces Derive from System.Object? C# Spec Says Yes, Eric Says No, Reality Says No
Need a Way to Reference 2 Different Versions of the Same 3Rd Party Dll
How to Implement Solid Principles into an Existing Project
The State of Linkers for .Net Apps (Aka "Please Sir, May I Have a Linker" 2009 Edition)
Learning Single Responsibility Principle with C#
Get Substring - Everything Before Certain Char
Why Does Microsoft.Office.Interop.Excel.Application.Quit() Leave the Background Process Running