Unable to calculate factorial , getting output as 0 in C - c

Tried calculating factorial of 65, got correct output. Anything greater than 65 results in output of 0. Shocking since I'm using unsigned long int. What is amiss ?
Code:
#include <stdio.h>
void factorial(int unsigned long);
int main()
{
int unsigned long num, result;
printf("\nEnter number to obtain factorial : ");
scanf("%ld", &num);
factorial(num);
}
void factorial (int unsigned long x)
{
register int unsigned long f = 1;
register int unsigned long i;
for (i=x;i>=1;i--)
f= f*i;
printf("\nFactorial of %lu = %lu\n",x,f);
}

You certainly did not get the correct result for 65! log2(65!) is just over 302 bits (Google it), so you'd need a long int of at least 303 bits to calculate that correctly. There is no computer in the world where long int is over 300 bits (let's see how this answer ages!).
The largest factorial you can compute in 64 bits is 20! (which is about 2.4e18).

Adding on to #JohnZwinck, the maximum value for a variable of type unsigned long long (ULLONG_MAX) is 18446744073709551615. So all the values greater than 20! are going to have a garbage value
You can refer to this for more information.

Related

Pow is not working for two double digit numbers

I have made a code to read two long integers (A and B) from standard input and output (to standard output) A to the power of B.
It works for 1^some huge number, 3^3 etc.
But not for 13^16.
I've tried to put long int ans to solve it, it gave me a different value but not the right one.
#include <stdio.h>
#include <math.h>
int main()
{
int x, n;
long int ans;
scanf("%d \n %d",&x, &n);
ans = pow(x,n);
printf("%d", ans);
return 0;
}
pow(1,anything) is always 1. pow(3, 3) is 27. These are both quite small numbers and easily fit into a 32 bit integer. pow(13,16) is (approximately) 6.65 x 1017. This is too big for a 32 bit integer to contain. It will go into a 64 bit integer (although pow(14, 17) will not). It's likely that your compiler treats a long as a 32 bit value, which is not uncommon. You could try long long which is likely to be 64 bits or int64_t which is explicitly 64 bits long.
Note though that the prototype for pow() is
double pow(double x, double y);
which means that it is returning a double precision floating point number and then coercing it into the type of your variable. double (a 64 bit floating point number) only has 53 bits of precision in its mantissa, which means you are not going to get the exact number when you cast it back to even a 64 bit integer. You could use powl() whose prototype is
long double powl(long double x, long double y);
But long double might be defined as 80 bits or 128 bits or even only 64 bits (Microsoft). It might give you the precision you need, but such is the nature of power operations, your input numbers won't have to get much bigger to overflow the precision of even the longest long double.
If you really need to raise large numbers to large powers, you are going to need a big integer library.
Rather than use floating point pow() and friends with their potential limited precision for an integer problem within 64 bits (1316 needs 60 bits), use an integer power function.
unsigned long long upow(unsigned x, unsigned y) {
unsigned long long z = 1;
unsigned long long xx = x;
while (y) {
if (y % 2) {
z *= xx;
}
y /= 2;
xx *= xx;
}
return z;
}
int main() {
printf("%llu\n", upow(3, 3));
printf("%llu\n", upow(13, 16));
}
Output
27
665416609183179841
If code needs to handle answers more the 64 bits, consider long double (with potential loss of precision) or big_integer libraries.
You have defined "ans" as long int then you are trying to print it as int (%d - Take the next argument and print it as an int ) So change printf("%d", ans) to printf("%ld",ans) . your code would look something like this :
#include <stdio.h>
#include <math.h>
int main()
{
int x, n;
long int ans;
scanf("%d \n %d",&x, &n);
ans = pow(x,n);
printf("%ld", ans);
return 0;
}

I've got an incorrect output for 13 factorial,how do i fix this?

My output
13!=1932053504
Expected output
13!=6227020800
I tried using int,long int but still the output remains the same
long int fact(long int num);
int main(){
long int n;
printf("Enter a number to find factorial: ");
scanf("%ld",&n);
printf("%ld!= %ld",n,fact(n));
}
long int fact(long int n){
if(n>=1)
return n*fact(n-1);
else
return 1;
}
Output:
13!=1932053504
The expected value exceeds 32 bits, what you get is the actual result trimmed to 32 bits:
1932053504 equals (6227020800 & 0xFFFFFFFF)
You'll have to verify capacity of int and long int in your environment, e.g. with print-ing their sizeof.
You should use long long int to make calculations on 64 bits. If you break that barrier also, you need to do more complicated stuff.
Note: use long twice, it is not a mistake - provided that the compiler supports 64-bit architectures.
If you are not interested in negative numbers, you can use unsigned long long int for some extra "comfort".

C - RSA Cryptosystem Decryption Issue (unsigned long long not big enough?)

I'm working on an assignment where I have to build an RSA Cryptosystem. I was able to encrypt the cipher key no problem however I'm having trouble decrypting it due to the result of the exponent being so large. I've tried using unsigned long long int but I'm still getting an output of 0.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
//Unsigned long long int power function
unsigned long long getPower(unsigned long long int base, int exponent){
unsigned long long result = 1;
int count = 0;
while(count != exponent){
result *= base;
count++;
}
return result;
}
int decryptFile(int cipherInt, int n, int d){
int plainInt;
unsigned long long int cipherIntLong = cipherInt;
unsigned long long int power = getPower(cipherIntLong, d);
printf("%llu\n", power);
return (int) plainInt;
}
int main(){
decryptFile(1394, 3127, 2011);
}
I should add that the professor made no mention of using a big number library so I'm sure we are most likely not supposed to use one for this assignment.
The maximum value of an unsigned 64-bit integer is 18,446,744,073,709,551,615
However, 1394^2011 is more around 1.296 x 10^6323. That is 7.02 x 10^6303 times larger than the maximum value of an unsigned 64-bit integer.
TL;DR: Use a BigInteger library, a really big one.
Seriously though, the main reason RSA can compute such large powers is because RSA operates under a modulus, so if we use Modular Exponentiation, we require far less computational power to reach the result. Calculating the result by raising the plaintext to the exponent and then applying the modulus at the end isn't computationally feasible.

Using unsigned data types in C

How to use unsigned int properly? My function unsigned int sub(int num1, int num2);doesn't work when user input a is less than b. If I simply use int, we can expect a negative answer and I need to determine which is larger before subtracting. I know that's easy but maybe there is a way to use unsigned int to avoid that?
For instance when a = 7 and b = 4, the answer is 3.000000. But when I flip them, the code gives me 4294967296.000000 which I think is a memory address.
#include <stdio.h>
unsigned int sub(int num1,int num2){
unsigned int diff = 0;
diff = num1 - num2;
return diff;
}
int main(){
printf("sub(7,4) = %u\n", sub(7,4));
printf("sub(4,7) = %u\n", sub(4,7));
}
output:
sub(7,4) = 3
sub(4,7) = 4294967293
Unsigned numbers are unsigned... This means that they cannot be negative.
Instead they wrap (underflow or overflow).
If you do an experiment with an 8-bit unsigned, then you can see the effect of subtracting 1 from 0:
#include <stdio.h>
#include <stdint.h>
int main(void) {
uint8_t i;
i = 1;
printf("i: %hhu\n", i);
i -= 1;
printf("i: %hhu\n", i);
i -= 1;
printf("i: %hhu\n", i);
return 0;
}
i: 1
i: 0
i: 255
255 is the largest value that an 8-bit unsigned can hold (2^8 - 1).
We can then do the same experiment with a 32-bit unsigned, using your 4 - 7:
#include <stdio.h>
#include <stdint.h>
int main(void) {
uint32_t i;
i = 4;
printf("i: %u\n", i);
i -= 7;
printf("i: %u\n", i);
return 0;
}
i: 4
i: 4294967293
4294967293 is effectively 0 - 3, which wraps to 2^32 - 3.
You also need to be careful of assigning an integer value (the return type of your sub() function) to a float... Generally this is something to avoid.
See below. x() returns 4294967293 as an unsigned int, but it is stored in a float... This float is then printed as 4294967296???
#include <stdio.h>
#include <stdint.h>
unsigned int x(void) {
return 4294967293U;
}
int main(void) {
float y;
y = x();
printf("y: %f\n", y);
return 0;
}
y: 4294967296.000000
This is actually to do with the precision of float... it is impossible to store the absolute value 4294967293 in a float.
What you see is called unsigned integer overflow. As you noted, unsigned integers can't hold negative numbers. So when you try to do something that would result in a negative number, seemingly weird things can occour.
If you work with 32-bit integers,
int (int32_t) can hold numbers between (-2^31) and (+2^31-1), INT_MIN and INT_MAX
unsigned int (uint32_t) can hold numbers between (0) and (2^32-1), UINT_MIN and UINT_MAX
When you try to add something to an int that would lead to a number greater than the type can hold, it will overflow.
unsigned int cannot be used to represent a negative variable. I believe what you wanted is to find the absolute value of the difference between a and b. If so, you can use the abs() function from stdlib.h. The abs() function takes in an int variable i and returns the absolute value of i.
The reason why unsigned int returns a huge number in your case is due to the way integers are represented in the system. You declared diff as an int type, which is capable of storing a negative value, but the same sequence of bits that represents -3 when interpreted as unsigned int represents 4294967296 instead.
It becomes a negative number, unsigned data types dont hold negative number, so instead it becomes a large number
"absolute value of the difference between a and b" does not work for many combinations of a,b. Any a-b that overflows is undefined behavior. Obviously abs(INT_MAX - INT_MIN) will not generate the correct answer.
Also, using abs() invokes undefined behavior with a select value of int. abs(INT_MIN) is undefined behavior when -INT_MIN is not representable as an int.
To calculate the absolute value difference of 2 int, subtract them as unsigned.
unsigned int abssub(int num1,int num2){
return (num1 > num2) ? (unsigned) num1 - num2 : (unsigned) num2 - num1;
}

Weird negative number after % operation

So I have something like the following,
int main()
{
int a[10];
int i=0;
int n=10000000000;
while (n!=0)
{
a[i++]=n%10;
printf("we have n is %d\n", n);
printf("we have n mod 10 is %d\n", n%10);
n/=10;
printf("we have%d\n", a[i]);
}
Somehow I would always get a negative number when the n mod 10 is '0‘, can someone tell me why?
int is too small to hold that number. You are getting an overflow which is causing n to actually be a negative number, so you get a negative value for the modulo operation.
The number is well past the limit of int on positive side.
You can run following codes to know the limits on integers in your OS
C:
#include <limits.h>
const int min_int = INT_MIN;
const int max_int = INT_MAX;
C++:
#include <limits>
const int min_int = std::numeric_limits<int>::min();
const int max_int = std::numeric_limits<int>::max();
What you need to do:
Choose another data type like double. You can also choose something like long int or simply long or size_t or int64_t which are each at least 64 bits.
For comparison:
signed int: -32767 to 32767
unsigned int: 0 to 65535
signed long:-2147483647 to 2147483647
unsigned long: 0 to 4294967295
Why negative?
The negative number happens because a typical signed int lies between -32767 to 32767
and then 32767 is represented as overflow. So this will be a negative number after truncating the overflow.
Also note that the sizeof a type is determined by the compiler,
which doesn't have to have anything to do with the actual hardware
(though it typically does); in fact, different compilers on the same
machine can have different values for these.

Resources