Reputation: 7838
Suppose we have int n = 2 ^ 31
then n-1 = 0111111111111111111111111111111
, this is what I can get locally.
My guess: convert n
to long
first -> subtraction -> slice to fit into int
.
System.out.println(n);
System.out.println(Integer.toBinaryString(n-1) + " : " + Integer.bitCount(n-1));
System.out.println(n-1);
// output
-2147483648
1111111111111111111111111111111 : 31
2147483647
But I found no specification to validate my guess, is there some?
From Integer overflow wiki.
When an arithmetic operation produces a result larger than the maximum above for an N-bit integer, an overflow reduces the result to modulo N-th power of 2, retaining only the least significant bits of the result and effectively causing a wrap around.
If my guess is just totally wrong, then how it actually works? Any link I can refer to?
Any help will be appreciated :)
Upvotes: 1
Views: 148
Reputation: 273135
That's just how arithmetic in two's complement works.
Subtracting 1 from 2^31 is the same as 2^31 plus -1, as per JLS §15.18.2,
For both integer and floating-point subtraction, it is always the case that
a-b
produces the same result asa+(-b)
.
And also that
If an integer addition overflows, then the result is the low-order bits of the mathematical sum as represented in some sufficiently large two's-complement format. If overflow occurs, then the sign of the result is not the same as the sign of the mathematical sum of the two operand values.
Now we can calculate the sum of 2^31 and -1 in binary. 2^31 is one 1 followed by 31 zeroes, which is -2147483648 in two's complement. -1 in two's complement is 32 ones, so we have:
1000 0000 0000 0000 0000 0000 0000 0000
+1111 1111 1111 1111 1111 1111 1111 1111
As you can see, the last bit on the left there overflows, but according to the second excerpt, we ignore that. Adding all those up, we get:
0111 1111 1111 1111 1111 1111 1111 1111
which is 2147483647
Upvotes: 1