Why there is a need of cast in the following program? - c

Posted the whole code(if needed)
/* multiplication of n1 and n2*/
#include<stdio.h>
int arr[200]; //for storing the binary representation of n2
int k=0; // to keep the count of the no of digits in the binary representation
void bin(int n)
{
if(n>1)
bin(n/2);
arr[k++]=n%2;
}
int main()
{
int n1=1500000;
int n2=10000000;
int i=0,t=0;
long long int temp,pro=0;
bin(n2); // calculating the binary of n2 and stroring in 'arr'
for(i=k-1; i>=0 ;i--)
{
temp = (n1*arr[i]) << t; /* Why need cast here ? */
pro = pro + temp;
t++;
}
printf("product: %lld",pro);
return 0;
}
In the above program, I am not getting the desired output. But when I do this:
temp = (n1*(long long int)arr[i]) << t;,
then I am getting the correct output !
I am not able to understand the above behavior ?

It seems likely that on your system int is 32 bits and long long int is 64 bits.
n1 and arr[i] are both int, and result of multiplication is then int. But there is not enough bits in int to hold the answer because it is too big.
When you cast one member of the operation to long long int, then result will also be long long int too.

n1, as well as arr[i], are integers. Without the cast, you get an integer multiplication (which may overflow), shift that integer left (again producing an integer result that may overflow), then assign that integer to temp.
If you cast arr[i] to long long, all calculations are done in long. So, if your integers are 32 bit (and thus limited to about 2e10), your integers will overflow, but the long longs, which should be 64 bit, will not.

I suspect that an int isn't large enough to store the result of (n1*arr[i]), so casting to a (long long int) gives enough room to store the result.
int Not smaller than short. At least 16 bits.
long long int Not smaller than long. At least 64 bits.
Have a look at C++ Data Types.

a multiplication between two integer goes into an integer unless you cast one of them to something else. So in the first multiplication the result is stored into an integer (32 bit signed on a 32 bit system), in the second case into a long long (64 bit unsigned on a 32 bit system). You may prefer using types like int64_t to have better portability.
You can use sizeof(int), sizeof(long long) to see the difference between the two.

Related

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?

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.

Multiplying two long numbers

I have tried to multiply to numbers i.e. 10000 and 10000 + 1 through C program. But I am not getting the correct output.
printf("%lld",(100000)*(100001));
I have tried the above code on different compilers but I am getting same 1410165408 instead of 10000100000.
Well, let's multiply
int64_t a = 100000;
int64_t b = 100001;
int64_t c = a * b;
And we'll get (binary)
1001010100000011010110101010100000 /* 10000100000 decimal */
but if you convert it to int32_t
int32_t d = (int32_t) c;
you'll get the last 32 bits only (and throw away the top 10):
01010100000011010110101010100000 /* 1410165408 decimal */
A simplest way out, probably, is to declare both constants as 64-bit values (LL suffix stands for long long):
printf("%lld",(100000LL)*(100001LL));
In C, the type which is used for a calculation is determined from the type of the operands, not from the type where you store the result in.
Plain integer constants such as 100000 is of type int, because they will fit inside one. The multiplication of 100000 * 100001 will however not fit, so you get integer overflow and undefined behavior. Switching to long won't necessarily solve anything, because it might be 32 bit too.
In addition, printing an int with the %lld format specifier is also undefined behavior on most systems.
The root of all evil here is the crappy default types in C (called "primitive data types" for a reason). Simply get rid of them and all their uncertainties, and all your bugs will go away with them:
#include <stdio.h>
#include <inttypes.h>
int main(void)
{
printf("%"PRIu64, (uint64_t)100000 * (uint64_t)100001);
return 0;
}
Or equivalent: UINT64_C(100000) * UINT64_C(100001).
Your two integers are int, that will make the result int too. That the printf() format specifier says %lld, which needs long long int, doesn't matter.
You can cast or use suffixes:
printf("%lld", 100000LL * 100001LL);
This prints 10000100000. Of course there's still a limit, since the number of bits in a long long int is still constant.
You can do it like this
long long int a = 100000;
long long int b = 100001;
printf("%lld",(a)*(b));
this will give the correct answer.
What you are doing is (100000)*(100001) i.e by default compiler takes 100000 into an integer and multiplies 100001 and stores it in (int)
But during printf it prints (int) as (long long int)

Wrong answer in C for long number calculations

long int k=(long int)(2000*2000*2000);
the above calculation is giving me wrong answer in C. What is wrong?
If a C integer constant fits in an int, it is of type int. So your expression is evaluated as:
long int k = (long int)((int)2000*(int)2000*(int)2000);
If int isn't large enough to hold the result of the multiplication, you'll get a signed integer overflow and undefined behavior. So if long is large enough to hold the result, you should write:
long k = 2000L * 2000L * 2000L;
The L suffix forces the type of the literal to long (long is equivalent to long int).
But on most platforms, even long is only a 32-bit type, so you have to use long long which is guaranteed to have at least 64 bits:
long long k = 2000LL * 2000LL * 2000LL;
The LL suffix forces the type of the literal to long long.
2000 is of type int, so 2000*2000*2000 is also of type int.
Assuming a 32-bit int (which is actually more than the standard requires, since an int is not required by the standard to represent a value more than 32767) the maximum representable value is about 2,147,483,647 (commas inserted for readability) which is less than 8,000,000,000.
You will probably want to do the calcuation as 2000LL*2000*2000 which takes advantage of multiplication being left-right associative, and will promote all the 2000 values to long long int before doing the multiplication. Your variable will also need to be of type long long int if you want a guarantee of being able to store the result.
Holt's answer is the correct one, I am just leaving this here as caveat!
You could try to use:
long long int
instead of
long int
However, in my local machine, it has no effect:
#include <stdio.h>
int main(void)
{
long int k=(long int)(2000*2000*2000);
printf("With long int, I am getting: %ld\n", k);
long long int n = 2000*2000*2000;
printf("With long long int, I am getting: %lld\n", n);
return 0;
}
Output:
With long int, I am getting: -589934592
With long long int, I am getting: -589934592
Warnings:
../main.c:6:36: warning: integer overflow in expression [-Woverflow]
long int k=(long int)(2000*2000*2000);
^
../main.c:9:32: warning: integer overflow in expression [-Woverflow]
long long int n = 2000*2000*2000;
Even this:
unsigned long long int n = 2000*2000*2000;
printf("With long long int, I am getting: %llu\n", n);
will overflow too.
There are two problems in your code:
long int is (on most architecture) not enough to store 8e9.
When you do 2000 * 2000 * 2000, operations are made using "simple" int, thus, int * int * int = int so you cast the result to an int and then to a long int.
You need to use long long int and specify that you want long long int:
long long int k = 2000LL*2000LL*2000LL;
Notice the extra LL after 2000 saying "It's 2000, but as a long long int!".
You can't just multiply the values together as ordinary precision integers and then cast the result to a higher precision, because the result has already overflowed at that point. Instead, the operands need to be higher precision integers before they're multiplied. Try the following:
#include <stdio.h>
int main(void)
{
long long int n = (long long int)2000*(long long int)2000*(long long int)2000;
printf("long long int operands: %lld\n", n);
return 0;
}
On my machine, this gives:
long long int operands: 8000000000

garbage value while usage of unsigned long int

Program:
#include<stdio.h>
int main()
{
unsigned long int i=1902;
int j=0;
while(j<10)
{
i=i*10;
printf("\n%lu",i);
j++;
}
}
Why am I getting correct results only upto 5 iterations? Please help me to get the correct answer for all iterations. Seeing the range, I changed my int to unsigned long int but still I'm unable to correct the error.
My guess is that you're on a 32-bit system, or using the Microsoft Visual Studio compiler. I guess that because it seems that unsigned long is 32 bits, which means the maximum value it can be is a little over 4 billion.
If you want a 64-bit value then you need to use unsigned long long, which is 64 bits on just about all PC-like systems.
Because at that point the value is out of the range that a unsigned long int can represent, that goes from 0 to 4,294,967,295.
unsigned long int is 4 bytes in almost every C Compiler.
here i is initialized with 1902.
You are multiplying the value of i by 10 at each iteration.
The range of signed long int is from -2,147,483,648 to 2,147,483,647.
By making the variable unsigned you can only double the range of positive integers, ie, from 0 to 4,294,967,295.
The value in variable i crosses maximum range of unsigned integer after 6 iterations. Hence the overflow and negative numbers displayed.
If you want to represent larger numbers use long long int whose size is 64 bits and the range is from −9223372036854775807 to 9223372036854775807.

Displaying very large number

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.

Resources