Earlier I came up with something, which I solved, but it got me later let\'s take a look at a similar example of what I was on:
int b = 35000000; //35million
int
Let me explain what is occuring here.
On:
int b= 35000000;
unsigned long n = ( 100 * 30000000 ) / b;
The value is incorrect because overflow happens at ( 100 * 30000000 )
But on:
unsigned long b= 35000000;
unsigned long n = ( 100 * 30000000 ) / b;
The value is correct, so what is happening?
In the first example b
is a int
, as said by Tony, an overflow happens because the register where the temporary value of ( 100 * 30000000 )
will be assigned is able to hold 32bit signed integers, that happens because 100 is an int and 30000000 is also an int AND because b
is also an int, the register in this case are smart, when ALL values on the right side are int
it assumes the values also have to be an int
but when a mighty unsigned long
comes to the party, it knows that dividing an int
by an unsigned long
, / b
is wrong, so it stores the value of ( 100 * 30000000 )
to an unsigned long
.
Another common solution is to typecast one of the constants to the larger, result type prior to operating on it. I prefer this method, since not everyone remembers all the possible suffixes. Including myself.
In this case, I'd use:
unsigned long n = ( (unsigned long)100 * 30000000 ) / b;
The sad part is that this is one thing assembly language—yes, assembly language—gets right that C, C++, and many other languages do not: The result of multiplying an M-bit integer by an N-bit integer is a (M+N)-bit integer, not a (max(M, N))-bit integer.
EDIT: Mark makes an interesting point: the compiler does not "look ahead" to where the result is stored in order to infer a result type. Thus, C++ demands that the result of any sub-expression, by itself, be deterministic. In other words, the exact type of 100 * 30000000
can always be determined without looking at any other piece of code.
Works (Output = 85):
unsigned long b= 35000000;
unsigned long n = ( 100 * 30000000 ) / b;
Not here, using:
#include <iostream>
int main() {
unsigned long b= 35000000;
unsigned long n = ( 100 * 30000000 ) / b;
std::cout << n << std::endl;
return 0;
}
the output is 527049830640 (and the compiler warned about the overflow even with the default warning level).
The point is that, as Mark Ransom already wrote, the type of an arithmetic operation is determined by the type of its operands.
The type of the constant 100 is int
, as is the type of the constant 30000000 (assuming 32-bit or larger int
s, would be long int
if int
is 16 bits). So the multiplication is performed at type int
, and with 32-bit int
s it overflows. The overflow is undefined behaviour, but wrap-around is the most common manifestation of that undefined behaviour, resulting in the value -1294967296
. Then the result of the multiplication is converted to the type of b
(since that is an unsigned type and - in C terminology - its integer conversion rank is not smaller than that of int
) for the division.
Conversion to an unsigned integer type means reduction modulo 2^WIDTH. If the width of unsigned long
is 32, the result of that last conversion is 2^32 - 1294967296 = 3000000000
, resulting in the quotient 85. But if - as on my system - the width of unsigned long
is 64 bits, the result of that conversion is 2^64 - 1294967296 = 18446744072414584320
.
The maximum number that can be represented in a 32-bit signed integer without overflow is 2147483647. 100*30000000 is larger than that.
The type of an arithmetic operation is completely independent of the type of the variable you're storing it into. It's based on the type of the operands. If both operands are of type int
, the result will be of type int
too, and that result will then be converted before it is stored in the variable.
In C++, there are programming elements called "literal constants".
For example (taken from here):
157 // integer constant
0xFE // integer constant
'c' // character constant
0.2 // floating constant
0.2E-01 // floating constant
"dog" // string literal
So, back to your example, 100 * 30000000
is multiplying two int
s together. That is why there is overflow. Anytime you perform arithmetic operations on operands of the same type, you get a result of the same type. Also, in the snippet unsigned long a = 30000000;
, you are taking an integer constant 30000000
and assigning that to the variable a
of type unsigned long
.
To get your desired output, add the ul
suffix to the end: unsigned long n = ( 100ul * 30000000ul ) / b;
.
Here is a site that has explanations for the suffixes.
why /b when b is unsigned long is still an interesting question
Because 100 * 30000000
is performed before you divide by b
and the operands are both of type int
.