I'm relatively new to C. I made this program to find the factorial of any number. Upon executing the program, when I provide 33 as the input - I get 2147483648 as the answer. If I provide 34, I get 0 as the answer.
Getting to my question - Why did I get 0 as the answer? The datatype I've used has a range of 0-4294967295. Am I getting 0 cause this is outside the range of unsigned int? Which datatype should I use if I want to get a large number as the output?
Compiler used - GCC 8.2.1
Here's the code -
#include<stdio.h>
#include<stdlib.h>
int fact(unsigned int n)
{
int result;
if(n==0 || n==1)
result=1;
else
result=n*fact(n-1);
return result;
}
int main()
{
unsigned int n,ans;
printf("Enter n:");
scanf("%u",&n);
ans=fact(n);
printf("Factorial of %u:%u",n,ans);
}
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.
The factorial grows very quickly. 13! is already outside the range representable by a 32-bit unsigned integer. Unsigned arithmetic returns the remainder when a result is not representable -- that is, you get only the least-significant bits of the true mathematical result. You could go a bit higher by using a wider data type, but not much. You need an arbitrary-precision arithmetic package and a lot of memory to go much further.
As for why the result you get for 34! is exactly zero, note that among the factors 1 * 2 * 3 * ... * 33 * 34 there are 17 that are multiples of two, 8 of which are also multiples of 4, 4 of which are also multiples of 8, two of which are multiples of 16, and one of which is 32. That's a total of 32 2s in the prime factorization of the mathematical result, so the remainder modulo 232 is exactly zero.
An unsigned int has a range of 0 to 2^32-1, or 2^32 = 4,294,967,296 different values. Assigning your result a value higher than 2^32-1 = 4,294,967,295 makes the value overflow. This simply means it loops back to 0, after which it can increase up to 4,294,967,295 again.
The first overflow happens when calculating 13!, when we would expect the result value to be 13! = 6,227,020,800. However, we did not take the overflow into account. The value of result will instead equal the remainder of the equation 13! % 2^32, or 1,932,053,504, because that's how much result increases after the last (and, in this case, only) loop back to 0.
Now, 33! or 34! represent values that are are unimaginably large, and make result overflow many times. We can calculate how many times 33! causes an overflow simply by dividing it by 2^32, resulting in around 2.02e27 overflows. However, your question isn't concerned with how many overflows happen, but with the value of the remainder after the last overflow. In this case, it equals 33! % 2^32 = 2,147,483,648. We can do the same for 34: 34! % 2^32 = 0.
What this means is that, coincidentally, 2^32 is a proper divisor of 34!. Or, isn't this coincidental after all?
Edit: like others have suggested, you should take a look at the GMP Bignum library with no limit in precision arithmetic except that of your machine.
Your assumption The datatype I've used has a range of 0-4294967295. is not right. you define ans parameter as unsigned int which has range of 0-4294967295 but in your fact function, you are using int which has range of -2,147,483,648 to 2,147,483,647.
So you should change yout code as this:
#include<stdio.h>
#include<stdlib.h>
unsigned int fact(unsigned int n)
{
unsigned int result;
if(n==0 || n==1)
result=1;
else
result=n*fact(n-1);
return result;
}
int main()
{
unsigned int n,ans;
printf("Enter n:");
scanf("%u",&n);
ans=fact(n);
printf("Factorial of %u:%u",n,ans);
}
You can also use unsigned long long instead of unsigned int which will support bigger numbers and is more suitable for factorial calculation.
#include<stdio.h>
#include<stdlib.h>
unsigned long long fact(unsigned int n)
{
unsigned long long result;
if(n==0 || n==1)
result=1;
else
result=n*fact(n-1);
return result;
}
int main()
{
unsigned int n;
unsigned long long ans;
printf("Enter n:");
scanf("%u",&n);
ans=fact(n);
printf("Factorial of %u:%u",n,ans);
}
More reading on data types and their range:
https://www.tutorialspoint.com/cprogramming/c_data_types.htm
You get 0 when you overflow your data types. Formally the behaviour on overflowing an int is undefined. If you switch consistently to unsigned types, then the overflow is such that the behaviour is consistent with arithmetic modulo 2 raised to the power of the number of bits in your unsigned type.
Since a large factorial is a multiple of a power of 2, 0 will be attained for a surprisingly small input, as you observe here.
while exploring linux code, came across many definition like below. If ULL is unsigned long long, why it has negative value -11? What the value of below macro?
#define BTRFS_FREE_SPACE_OBJECTID -11ULL
-11ULL is the same as - (11ULL). 11ULL is an unsigned long long with value 11. If you read up how arithmetic operations on unsigned types work, if the mathematical result does not fit into the range, then the largest value + 1 is added or subtracted repeatedly.
The mathematical result -11 doesn't fit, so the largest unsigned long long + 1 is added, and -11ULL gives ten less than the largest possible unsigned long long value. A huge positive number, not negative.
unsigned int a=-1;
is the same as:
unsigned int a=0xffffffff;
I try to write a program for reverse the user input number.
The user input range is from 0 < a < 4294967295,
here is EDITED code.
unsigned long int reverseNumber(unsigned long int num)
{
unsigned long int rev = 0;
while (num > 0)
{
rev = rev *10 + (num%10);
num = num/10;
}
return rev;
}
The problem is when I input 4294967295, it will output 1632727628.
Why? I have no idea why it happened.
How can I reverse the 4294967295.
I had changed it to unsigned long int, printf by using %lu, but still output 1632727628. Why?
The reverse of 4294967295 is 5927694924 which is greater than the range of unsigned int
In your system, unsigned int is 32-bit wide, hence the max value that an unsigned int can represent is 4294967295 i.e. 0xFFFFFFFF. That is why your result is overflowing and whatever remains in 32 bits is shown as output.
If you represent 5927694924 in hex, it is 0x16151724C which has extra 33rd bit 1, which is discarded and hence output is 0x6151724C which is 1632727628 in decimal.
To print it on screen you need a greater data type like unsigned long long or uint64_t or unsigned long (on 64-bit systems only), whatever your compiler supports for 64 bit integers.
The reverse of 4294967295 is 5927694924, which is greater than 4294967295, which is the greatest integer which can be stored on 32 bit.
The problem is when I input 4294967295, it will output 1632727628. Why?
unsigned int can store 2^32-1 max. The reverse of 4294967295 is 5927694924 which is much bigger than 2^32-1. Hence the out put is 1632727628. 1632727628 is in fact 5927694924 % 4294967296
To solve this you should have used unsigned long it. But again if the number is great than highest long it'll overflow again.
I am trying to run this code where i use short int.
int main() {
short int i=0;
while(++i)
printf("%u\n", i);
}
Ouput (using short int):
1
2
3...
32767
4294934528
.
.
4294967295(last value)
why is there sudden jump in value after 32767 any explanations??
I am using linux(32 bit) os.
Signed integer overflow is undefined behavior. Your program pushes i beyond the bounds of what can be stored in a short, so the program is free to do absolutely anything.
A signed short ranges from -32768 to 32767 and an unsigned short ranges from 0 to 65535. So you are exceeding data size for signed int short.
As we know that 4294967295 is the largest number in unsigned int if I multiply this number by itself then how to display it? I have tried:
long unsigned int NUMBER = 4294967295 * 4294967295;
but still getting 1 as answer.
You are getting an overflow. Consider the muplication in hexadecimal:
0xffffffff * 0xffffffff == 0xfffffffe00000001
^^^^^^^^
only the last 32 bits are returned
The solution is to use a larger type such as long long unsigned:
long long unsigned int NUMBER = 4294967295ULL * 4294967295ULL;
The suffix ULL means unsigned long long.
See it working online: ideone
The multiplication overflows.
#include <stdio.h>
int main()
{
unsigned int a = 4294967295;
unsigned int b = 4294967295;
// force to perform multiplication based on larger type than unsigned int
unsigned long long NUMBER = (unsigned long long)a * b;
printf("%llu\n", NUMBER);
}
You state in your question that you know max int is equal to 4294967295. That means that you can't store a number larger than that if you are using unsigned int.
C longs store up to 18,446,744,073,709,551,615 when unsigned on a 64 bit unix system [source] so you need only suffix your numbers with UL : 4294967295UL
If you aren't using a 64-bit unix system then you should use long long unsigned int and suffix with LL
Yes, it's an overflow. If you are using c, there isn't any easy way to do such big number multiply as i knew. Maybe you need write one by yourself. In fact some language support such features originally.