Wrong answer in C for long number calculations - c

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

Related

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

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.

long long int initialization warnings

2 Questions
First, while
long long int num = 1000000000000;
works fine
long long int num = 4014109449;
gives
warning: this decimal constant is unsigned only in ISO C90 [enabled by default]
What does it mean ?
Secondly
long long int num = 1000000*1000000;
gives an overflow warning
while
long long int num = 1000000000000;
is ok,even though they are same.How do i get rid of it? Multiplication gives a garbage value
The problem is that the value 4014109449 is an unsigned long int in C90 but a long long int in C99 because it is too large for a 32-bit long int. While 1000000000000 is too large for any 32-bit type, so is automatically a long long int. The warning relates to the fact that the behaviour differs between C90 and C99.
The solution is to force type agreement between the literal and the variable type by using an appropriate type suffix. In this case:
long long num = 4014109449LL ;
or use a type cast:
long long num = (long long)4014109449 ;
Similarly the expression 1000000 * 1000000 is a multiply of two int types and has an int result, but causes an overflow - there is no automatic promotion to a larger type for int expressions. The solution is again to be explicit about the type of the literal:
long long num = 1000000LL * 1000000LL;
or you can also use a type cast on one or both operands.
long long num = (long long)1000000 * 1000000;
In C90, the type of an unsuffixed decimal integer constant (literal) is the first of
int
long int
unsigned long int
that can represent its value without overflow.
In C99 and later, it's the first of
int
long int
long long int
that can represent its value.
The value 4014109449 happens to be representable as a 32-bit unsigned integer, but not as a 32-bit signed integer. Assuming your system has 32-bit longs, that constant's type is unsigned long int in C90, long long int in C99 and C11.
That's what the warning is telling you. The type of the constant changes depending on which version of the C standard your compiler conforms to.
Note that, regardless of its type, the value of 4014109449 will always be correct, and in your declaration:
long long int num = 1000000000000;
that value will always be correctly converted to long long. But it certainly wouldn't hurt (and would silence the warning) to add a LL suffix to make it explicit that you want a value of type long long:
long long int num = 1000000000000LL;
As for this:
long long int num = 1000000*1000000;
assuming you have 32-bit ints, the constant 1000000 is of type int, and the result of multiplying two int values is also of type int. In this case, the multiplication will overflow. Again, you can avoid the problem by ensuring that the constants are of type long long int:
long long int num = 1000000LL * 1000000LL;
(Note that you can use lowercase ll, but it's a bad idea, since it can be difficult to distinguish the letter l from the digit 1.)

unsigned long long int constant value vs. multiplicative value

I tried the below, and it seems that 'test' results in wrong value. 2500*2500*2500 == 15625000000, why the below operations result in different outcome?
unsigned long long int test = 2500*2500*2500;
fprintf(stderr, "*************** test = %lld, %llu\n", test, test);
unsigned long long int test2 = 15625000000;
fprintf(stderr, "*************** test2 = %lld, %llu\n", test2, test2);
Result:
*************** test = -1554869184, 18446744072154682432
*************** test2 = 15625000000, 15625000000
2500 * 2500 * 2500 is never promoted past int, so the signed overflow that occurs (which is, by the way, UB) stops the correct calculation from being performed.
To allow it, you must tell the compiler that your literals are of a particular type. There are two ways to do this:
By casting—casting a literal is generally handled at compile-time and has no runtime overhead:
unsigned long long int test = (unsigned long long int)2500 * (unsigned long long int)2500 * (unsigned long long int)2500;
Note that the cast is performed on the multiplicands individually. If the result of the operation were cast (e.g. (unsigned long long int)(2500 * 2500 * 2500)) then the cast would be too late to preserve the data.
By suffixing:
unsigned long long int test = 2500ULL * 2500ULL * 2500ULL;
This is exactly as efficient at runtime as casting of literals is, but depending on usage may be easier or harder to read. Suffixing must be applied directly to a literal (it cannot be applied to the result of an operation, so (2500 * 2500 * 2500)ULL is illegal.)
2500*2500*2500 is not an unsigned long long just because you're copying it to an unsigned long long. The multiplications are done with ints, so the result of the multiplication is an int. By the time the upgrade to unsigned long long happens, it's too late. Use 2500ULL.

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.

Question about C datatype and constant

Greetings!
I was experimenting with C language till I encountered something very strange.
I was not able to explain myself the result shown below.
The Code:
#include <stdio.h>
int main(void)
{
int num = 4294967295U;
printf("%u\n", num);
return 0;
}
The Question:
1.) As you see, I created an int which can hold numbers between -2147483648 to 2147483647.
2.) When I assign the value 4294967295 to this variable, the IDE shows me a warning message during compilation because the variable overflowed.
3.) Due to curiosity I added a U (unsigned) behind the number and when I recompiled it, the compiler did not return any warning message.
4.) I did further experiments by changing the U (unsigned) to L (long) and LL (long long). As expected, the warning message still persist for these two but not after I change it to UL (unsigned Long) and ULL (unsigned long long).
5.) Why is this happening?
The Warning Message :(For steps 2)
warning #2073: Overflow in converting constant expression from 'long long int' to 'int'.
The Warning Message:(For steps 4 LL & L)
warning #2073: Overflow in converting constant expression from 'long long int' to 'long int'.
And last, thanks for reading my question, your teachings and advices are much appreciated.
As per the ISO C99 standard, section 6.4.4.1 (Integer Constants), subsection Semantics, the type of an integer constant is the first type of the following table where the value can be represented:
Octal or Hexadecimal
Suffix Decimal Constant Constant
none int int
long int unsigned int
long long int long int
unsigned long int
long long int
unsigned long long int
u or U unsigned int unsigned int
unsigned long int unsigned long int
unsigned long long int unsigned long long int
l or L long int long int
long long int unsigned long int
long long int
unsigned long long int
both u or U unsigned long int unsigned long int
and l or L unsigned long long int unsigned long long int
ll or LL long long int long long int
unsigned long long int
both u or U unsigned long long int unsigned long long int
and ll or LL
Particular implementations can have extended integer types that follow the same pattern as above.
Perhaps, by default, the compiler assumes you're typing in signed integers. When you give it 4294967295, that number doesn't fit into a 4-byte integer, so it uses an 8-byte integer to store it, instead. Then it has to do a lossy conversion (long long, AKA 8-byte, to long, AKA 4-byte), so it gives you a warning.
However, when you type 4294967295U, it knows you want an unsigned integer. That number fits into a 4-byte unsigned integer, so it has type long int, and no lossy conversion is necessary. (You're not losing data by going from unsigned long int to long int, just mis-representing it.)

Resources