7

I have a simple c++ app that performs the following calculations

long long calcOne = 3 * 100000000;     // 3e8, essentially
long long calcTwo = 3 * 1000000000;    // 3e9, essentially
long long calcThree = 3 * 10000000000; // 3e10, essentially

If I write the result of each calculation I get the following output:

calcOne = 300000000
calcTwo = -1294967296
calcThree = 30000000000

So why does the second calculation fail? As far as I can tell it is within the limits of a long long type (calcThree was larger...).

I am using Visual Studio 2015 on Windows 10. Thanks in advance.

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
John Voss
  • 107
  • 1
  • 4
  • 2
    integer overflow - you are using an integer literal that fits in an `int` and after the multiplication it overflows - only after that is it converted to `long long` - you can explicitly force the literal to be treated as a `long long` by attaching a `ll` suffix – UnholySheep Mar 22 '17 at 18:52
  • I can confirm I get the same result on VS2015, Windows 10 , 64bit build. – JimmyNJ Mar 22 '17 at 18:54
  • @Rama dead on agree with you, but this has better answers. Going to change the title of this question to make it a bit more useful to searching. – user4581301 Mar 22 '17 at 19:04
  • Another duplicate: [Why does long long n = 2000\*2000\*2000\*2000; overflow?](https://stackoverflow.com/q/66354756) – Peter Cordes Feb 25 '21 at 09:00

4 Answers4

12

Integer constants are, by default ints.

1000000000

That can fit into an int. So, this constant gets parsed as an int. But multiplying it by 3 overflows int.

10000000000

This is too big to an int, so this constant is a long long, so the resulting multiplication does not overflow.

Solution: explicitly use long long constants:

long long calcOne = 3 * 100000000LL;     // 3e8, essentially
long long calcTwo = 3 * 1000000000LL;    // 3e9, essentially
long long calcThree = 3 * 10000000000LL; // 3e10, essentially
Sam Varshavchik
  • 114,536
  • 5
  • 94
  • 148
2

What you do with a result doesn't affect how that result is calculated. So the fact that you store the result in a long long doesn't change the fact that the numbers you multiplied in the second line of code were not long longs and so they overflowed. In the third line of code, the constant is a long long, so the multiplication is performed on long longs.

David Schwartz
  • 179,497
  • 17
  • 214
  • 278
2

The compiler saw this

long long calcOne = (int) 3 * (int) 100000000;     // 3e8, essentially
long long calcTwo = (int) 3 * (int) 1000000000;    // 3e9, essentially
long long calcThree = (int) 3 * (long long) 10000000000; // 3e10, essentially

And so the calcTwo right hand value was inferred as an int type and then over flowed. You see the over flow as a negative long.

long long calcOne = 3LL * 100000000LL;     // 3e8, essentially
long long calcTwo = 3LL * 1000000000LL;    // 3e9, essentially
long long calcThree = 3LL * 10000000000LL; // 3e10, essentially

To avoid this in the future, be explicit as to the types of your static values.To tell the compiler a number is a long long post fix it with LL.

JimmyNJ
  • 1,134
  • 1
  • 8
  • 23
0

Most programming languages rank number types by size. The size/rank/type of a numeric expression is (usually) the type of the highest-ranked value in the expression.

Example: int * double -> double

Your program has: long long int = int * int.

What's happening is that the result of int * int is an int. So your program will multiply first and treat the result in a signed integer (maximum value ~= 2 billion, so it wraps around into negative numbers). Then, this negative value gets stored in the long long int.

300 million (your first multiplication) fits in an int. No problem there. I'm guessing the third works properly because the compiler is smart enough to know that 30 billion doesn't fit in a 32-bit int and automatically gives it a 64-bit long long int.

user1258361
  • 1,133
  • 2
  • 16
  • 25