Why does long long n = 2000*2000*2000*2000; overflow?
Solution 1
Because 2000
is an int
which is usually 32-bit. Just use 2000LL
.
Using LL
suffix instead of ll
was suggested by @AdrianMole in, now deleted, comment. Please check his answer.
By default, integer literals are of the smallest type that can hold their value but not smaller than int
. 2000
can easily be stored in an int since the Standard guarantees it is effectively at least a 16-bit type.
Arithmetic operators are always called with the larger of the types present but not smaller than int
:
-
char*char
will be promoted tooperator*(int,int)->int
-
char*int
callsoperator*(int,int)->int
-
long*int
callsoperator*(long,long)->long
-
int*int
still callsoperator*(int,int)->int
.
Crucially, the type is not dependent on whether the result can be stored in the inferred type. Which is exactly the problem happening in your case - multiplication is done with int
s but the result overflows as it is still stored as int
.
C++ does not support inferring types based on their destination like Haskell does so the assignment is irrelevant.
Solution 2
The constants (literals) on the RHS of your first line of code are int
values (not long long int
). Thus, the mulitplications are performed using int
arithmetic, which will overflow.
To fix this, make the constants long long
using the LL
suffix:
long long int n = 2000LL * 2000LL * 2000LL * 2000LL;
In fact, as noted in the comment by Peter Cordes, the LL
suffix is only actually needed on either the first (leftmost) or second constant. This is because, when multiplying types of two different ranks, the operand of lower rank is promoted to the type of the higher rank, as described here: Implicit type conversion rules in C++ operators. Furthermore, as the *
(multiplication) operator has left-to-right associativity, the 'promoted' result of the first multiplication propagates that promotion to the second and third.
Thus, either of the following lines will also work without overflow:
long long int n1 = 2000LL * 2000 * 2000 * 2000;
long long int n2 = 2000 * 2000LL * 2000 * 2000;
Note: Although lowercase suffixes (as in 2000ll
) are valid C++, and entirely unambiguous to the compiler, there is a general consensus that the lowercase letter, 'ell', should be avoided in long
and long long
integer literals, as it can easily be mistaken, by human readers, for the digit, 1
. Thus, you will notice that 2000LL
(uppercase suffix) has been used throughout the answers here presented.
Solution 3
2000*2000*2000*2000
is a multiplication of 4 int
values, which returns an int
value. When you assign this int
value to long long int n
the overflow already happend (if int
is 32 bit the resulting value won't fit).
You need to make sure that the overflow does not occur, so when you write
long long int n = static_cast<long long int>(2000)*2000*2000*2000;
you make sure that you are doing a long long int
multiplication (long long int
multiplied with int
returns a long long int
, so no overflow in your case).
A shorter (and better way) is to write 2000LL
or 2000ll
instead of the static_cast
. That gives the integer literal the right type. This is not needed for 2000 which fits into an int
but it would be needed for higher values that don't fit into an int
.
long long int n = 2000LL*2000*2000*2000;
long long int n = 2000LL*2000LL*2000LL*2000LL;
Solution 4
The other answers (as of this writing) appear to not have been explicit enough to answer the question as stated. I'll try to fill this gap.
Why does the first one overflow (multiplying integer literal constants to assign to a long long)?
The expression
long long int n = 2000*2000*2000*2000;
is evaluated as follows:
long long int n = ((2000*2000)*2000)*2000;
where the steps are (assuming 32-bit int
):
-
(2000*2000)
is a multiplication of twoint
values that yields 4000000, anotherint
value. -
((2000*2000)*2000)
is a multiplication of the above yieldedint
value 4000000 with anint
value 2000. This would yield 8000000000 if the value could fit into anint
. But our assumed 32-bit int can store a maximum value of 231-1=2147483647. So we get overflow right at this point. - The next multiplication would happen if there hadn't been overflow above.
- The assignment of the resulting
int
product would happen (if not the overflow) to thelong long
variable, which would preserve the value.
Since we did have overflow, the statement has undefined behavior, so steps 3 and 4 can't be guaranteed.
What's different about it vs. the second or third ones?
long long int n = pow(2000,4);
The pow(2000,4)
converts 2000
and 4
into double
(see some docs on pow
), and then the function implementation does its best to produce a good approximation of the result, as a double
. Then the assignment converts this double
value to long long
.
long long int n = 16000000000000;
The literal 16000000000000
is too large to fit into an int
, so its type is instead the next signed type that can fit the value. It could be long
or long long
, depending on the platform. See Integer literal#The type of the literal for details. then the assignment converts this value to long long
(or just writes it, if the literal's type was long long
already).
Solution 5
The first is a multiplication using integers (typically 32 bit). It overflows because those integers cannot store 2000^4
. The result is then cast to long long int
.
The second calls the pow function which casts the first argument to double
and returns a double
. The result is then cast to long long int
. There is no overflow in this case because the math is done on a double value.
Related videos on Youtube
Fabbiucciello
Updated on June 08, 2022Comments
-
Fabbiucciello about 2 years
long long int n = 2000*2000*2000*2000; // overflow long long int n = pow(2000,4); // works long long int n = 16000000000000; // works
Why does the first one overflow (multiplying integer literal constants to assign to a long long)?
What's different about it vs. the second or third ones?
-
Jarod42 over 3 years
pow(2000,4)
uses ..double
,2000*2000*2000*2000
usesint
. -
drescherjm over 3 yearsThe first one is calculated using
int
. 2000 is an int. Not long long int -
Fabbiucciello over 3 yearsand why does it overflow?
-
drescherjm over 3 yearsBecause the maximum 32 bit int value is
2^31 − 1
which is2,147,483,647
is smaller than 2000* 2000* 2000*2000 and since all the 2000s are int the calculation is done as an int. Not as a long long int -
David Schwartz over 3 yearsPeriodic reminder: What you do with the result of an operation does not affect how that result is computed.
-
Peter Cordes over 3 yearsIt's a duplicate of Long integer overflow in C++, but this ended up getting better answers than that had, so I closed that as a duplicate of this. I think the question @Cody found is about something else: relative precision of huge floats, making 1ulp > 1.0. Not integer overflow at all.
-
Peter Cordes over 3 years@Cody: I eventually found some good duplicates, like 3 * 1000000000 overflows as an int, but the variable is long long. Why? and long long is 8 bytes, but I get integer overflow?, but this one has the best answers so they should be dups of this. (e.g. other questions have answers with mis-statements like all literals have type int, which isn't true for larger numbers. Or that appending an LL to any of the constants would avoid overflow, rather than 1st or 2nd for operator precedence.)
-
Peter Cordes over 3 yearsTL:DR: This seems like the current best canonical Q&A I've found for overflowing expressions with integer literals, so I've dup-hammered or edited the dup list of others to point at this one.
-
Steve Summit over 3 years@PeterCordes Thanks. And though it's not a dup, it might be nice to cross-reference with "Why did
double d = 1 / 3;
give me 0?" -
chux - Reinstate Monica over 3 yearsSee also reasons not to use 1000 * 1000 * 1000.
-
-
Adrian Mole over 3 yearsClang says: warning : use of old-style cast [-Wold-style-cast]!
-
ShadowRanger over 3 years@AdrianMole: Presumably you could use C++ style casting,
static_cast<long long int>(2000)
to avoid the issue (though I usually drop the impliedint
part). That said,2000LL
is way simpler in this case. -
Peter Cordes over 3 years
*
groups left to right, so only the left-most2000LL
actually needs an LL suffix. The others will all get implicitly promoted tolong long
as evaluation of the other 2*
operators proceeds. Using LL on all of them is certainly not a bad thing; less for humans to worry about when reading code, but just for future reference. Implicit type conversion rules in C++ operators -
Peter Cordes over 3 years
int
can be as narrow as 16-bit, and is on some modern embedded microcontrollers (like AVR or MSP430), so you need to worry about this for portability if the final value is > 32767. (You're unlikely to find a C implementation with 64-bitint
, although IIRC there are a rare few. And historically int might not be exactly 32.) It's hard to be precise without bloating answers, but you could say "usingint
(normally 32-bit)" -
HolyBlackCat over 3 years@AdrianMole
-Wold-style-cast
is not included in-Wall -Wextra
though. I see no harm in C-style casts to non-pointer, non-reference types. -
Adrian Mole over 3 years@HolyBlackCat I use clang-cl via Visual Studio (with
/Wall
) and that does give the warning. Also, why use the do-anything C-style cast when the softerstatic_cast
will suffice? -
Werner Henze over 3 years@AdrianMole You are right,
static_cast
would be a better alternative. I don't know why, but I was thinking more C than C++ here. -
HolyBlackCat over 3 years@AdrianMole Because it's less typing. :)
-
Adrian Mole over 3 years@PeterCordes I've incorporated your comment into my answer - hope you don't mind! I was a bit hesitant, at first, because the issue is (partially) dealt with in the other answers (particularly Werner's). Hopefully, though, I've explained the issue in more detail.
-
Peter Cordes over 3 yearsIt's always a good thing when people find ways to improve posts based on comments, including borrowing some of the wording, especially on canonical Q&As like this which hopefully many future readers will eventually see. Improving posts is exactly what comments are for, so cheers. :) And yeah, I only noticed Werner's answer after commenting here. Explaining this point is definitely good; while looking for duplicates (which I ended up closing as dups of this, because it has good answers), I found some which incorrectly stated that making any of the numbers LL worked.
-
JDługosz over 3 yearsre no harm in C style casts -- when reading the source code, any C-style cast is an automatic code review issue. So leaving it that way wastes time and attention every time it is looked at again. Function-style is the same number of characters.
-
Federico Poloni over 3 yearsWouldn't that work also if the LL is on the third constant? The first two get multiplied in
int
arithmetic, but that's fine, because 2000*2000 fits in anint
. -
Adrian Mole over 3 years@FedericoPoloni Yes, in the case of these particular four values, that would work. However, the aim of my answer is to address more general cases, in which the the promotion must be applied from the get-go. But I would also maintain that using the suffix on all four is the best/clearest coding style: if you want
long long
arithmetic, uselong long
operands. -
Adrian Mole over 3 years@FedericoPoloni Also note (perhaps more importantly) that
2000 * 2000
will overflow ifint
is 16-bits wide. IIRC, the C++ standard allows 16-bitint
, 32-bitlong
and 64-bitlong long
. -
Samuel Liew over 3 yearsComments are not for extended discussion; this conversation has been moved to chat.
-
Zilog80 over 3 years@MaksimKuzmin The question has the appearance of simplicity, yet it hides the underlying system representation of numbers at CPU level and how C/C++ language deals with it. In fact, it's not a so simple question, so this very elaborate answer is meaningful and useful regarding the question.
-
Lewis Kelsey over 3 years@Zilog80 yeah I just wanted a guide on literals to refer back to
-
Zilog80 over 3 years@LewisKelsey You means it would have been better to put links to the literals documentation instead of embedding it, and i fully agree. I was mainly pointing the fact that numbers representation at CPU level worths a bit of elaboration [but not indeed an embedded excerpt of documentations].
-
Yves Gurcan over 3 yearsThank you for your detailed answer!