Two Ways to Interpret Integer Overflow - java

I have read here (https://stackoverflow.com/a/27762490/4415632) that when integer overflow occurs, the most significant bits are simply cut off.
However, I have also read here (https://stackoverflow.com/a/27747180/3808877) that when overflow occurs, "the value becomes the minimum value of the type, and start counting up again." Which one is correct, or are both answers correct? If so, can anyone show me why those two interpretations are equivalent to each other?

Both are correct, it depends on context. One is the result of casting and one is the result of overflow. Those are different operations. For example, if you cast Long.MAX_VALUE to an int that is a cast operation
System.out.println((int) Long.MAX_VALUE); // <-- -1
If you overflow an int by adding one to Integer.MAX_VALUE then
System.out.println(Integer.MAX_VALUE + 1); // <-- Integer.MIN_VALUE

Both interpretations are correct, because they are actually the same.
Let's look at the maths to see why.
Java stores values in byte, short, char, int and long in a format called two's complement.
In case of byte, short, int and long it is signed, in case of char it is unsigned.
One of the attributes of the two's complement format is that for most operations it does not matter whether the value is interpreted as signed or unsigned as the resulting bit pattern would be the same.
To shorten things, I'll explain it using byte, but the other types work along the same scheme.
A byte has 8 bits. The topmost bit is interpreted as sign bit. So, the bit pattern goes like this:
snnn nnnn
The separation into two groups of 4 bits each is called Nibble and is performed here for pure readability. As a side note, a nibble can be represented by a hexadecimal digit.
So there are 8 bits in a byte, and each bits could be 0 or 1. This leaves us with 2^8 = 256 different values that could be stored in a byte.
Here are some sample values:
0000 0000 -> 0
0000 0001 -> 1
0000 0010 -> 2
0100 0000 -> 64
0111 1111 -> 127
1000 0000 -> -128
1111 1110 -> -2
1111 1111 -> -1
The 2's complement value of signed numbers which are negative, i.e. the sign bit is set, is created by taking the positive value of the 8 bits and subtracting the range, i.e. in case of a byte by subtracting 256.
Now let's see what happens if you take -1 and add 1.
1111 1111 -1 / 255
+ 0000 0001 1
--------------
= 1 0000 0000 -0 / 256 intermediate result
= 0000 0000 0 / 256 result after dropping excess leading bits
There is an overflow. The result would need 9 bits now, but the byte only has 8 bits, so the most significant bit is lost.
Let's look at another example, -1 plus -1.
1111 1111 -1 / 255
+ 1111 1111 -1 / 255
--------------
= 1 1111 1110 -2 / 510 intermediate result
= 1111 1110 -2 / 254 result after dropping excess leading bits
Or this, 127 plus 5.
0111 1111 127
+ 0000 0101 5
--------------
= 1000 0100 132 / -124
As we can see, the leading bits are dropped and this actually is what leads to the effect that causes it to overflow by "starting to count from the minimum value again".

I add another option: a processor trap. Some processors will generate a trap on integer overflows. When available, this feature usually can be enabled in user mode by setting a bit in the processor status register.

Related

Is it possible to predict the arithmetic result when it's overflow already?

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 :)
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 as a+(-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

-1 left shift by 31

System.out.println((-1<<31));
Why this is giving output -2147483648
I know -1<<31 will give 10000000000000000000000000000000, so it should give ans (int)Math.pow(2,31) that is equals to 2147483648
-1<<31 gives 10000000000000000000000000000000 which is -2147483648, not 2147483648. Note that the left bit is the sign bit, so if it's 1, this is a negative number.
BTW, 1<<31 would also give you -2147483648, since 2147483648 is higher than Integer.MAX_VALUE. On the other hand, 1L<<31 would give you 2147483648, since the result would be a long.
I know -1<<31 will give 100000000000000000, so it should give ans (int)Math.pow(2,31) that is equals to 2147483648
That would be the case if int was a two's complement unsigned primitive; but int is signed.
You are correct in the fact that in binary this indeed gives what you say; however, since this is a signed two's complement primitive, the result will be x(0) * 2^0 + x(1) * 2^1 + ... + x(n-2) * 2^(n-2) - x(n-1) * 2^(n-1) (minus, not plus), where x(y) is the value of the y-th bit, counting from 0.
Hence your result.
Nowadays in most architectures numbers are stored in 2-complements, see Wikipedia.
So your result is correct. The sign bit is set and all the resting zeros (because 2-complement) makes that the most negative number for that data type, see here.
Thinking in 2-complements
-1 is represented by 1111 1111 1111 1111 1111 1111 1111 1111
31 shifts to the left yields
1000 0000 0000 0000 0000 0000 0000 0000 which represents -2.147.483.648

Binary presentation of negative integer in Java

Please, help me to understand binary presentation of negative integers.
For example we have 5.
Binary presentation of 5 is 00000000.00000000.00000000.00000101.
And as I understand binary presentation of -5 should be like 10000000.00000000.00000000.00000101.
But output is 11111111.11111111.11111111.11111011.
I have 2 question:
1) Why here is so much 1 bits.
2) What I really cant understand it last 3 bits 011. It looks like 3. Even +1 or -1 it'll be 100 or 010
Thanks
Your understanding of what those negative numbers should look like is flawed. Java uses two's complement for negative numbers and the basic rule is to take the positive, invert all bits then add one. That gets you the negative.
Hence five is, as you state:
0000...00000101
Inverting that gives you:
1111...11111010
Then adding one gives:
1111...11111011
The bit pattern you have shown for -5 is what's called sign/magnitude, where you negate a number simply by flipping the leftmost bit. That's allowed in C implementations as one of the three possibilities(a), but Java uses two's complement only (for its negative integers).
(a) But keep in mind there are current efforts in both C and C++ to remove the other two encoding types and allow only two's complement.
And as I understand binary presentation of -5 should be like 10000000.00000000.00000000.00000101.
That would be right if Java used a Sign and Magnitude representation for integers. However, Java uses Two's Complement representation, so the rest of the bits are changed in accordance with the rules of that representation.
The idea behind two's complement representation is that when you add a number in such representation to another value dropping the extra bit on the most significant end, the result would be as if you subtracted a positive number of the same magnitude.
You can illustrate this with decimal numbers. In a two-digit representation, the value of 99 would behave like -1, 98 would be like -2, 97 like -3, and so on. For example, if you drop the top digit in 23 + 99 = [1]22, so 99 behaved like -1. 23 + 98 = [1]21, so 98 behaved like -2.
This works the same way with two's complement representation of binary numbers, except you would drop the extra bit at the top.
http://en.wikipedia.org/wiki/Two%27s_complement
The way negative numbers are stored is that the most significant bit (e.g. the bit representing 2^31 for a 32 bit number) is regarded as negative. So if you stored all 1s, you would add up
(-2^31) + 2^30 + 2^29 + ... + 2^1 + 2^0
which makes -1.
Small negative numbers will be mostly ones under this representation.
Here is an example for 2's compliment:
If you have -30, and want to represent it in 2's complement, you take the binary representation of 30:
0000 0000 0000 0000 0000 0000 0001 1110
Invert the digits.
1111 1111 1111 1111 1111 1111 1110 0001
And add one.
1111 1111 1111 1111 1111 1111 1110 0010
Converted back into hex, this is 0xFFFFFFE2. And indeed, suppose you have this code:
#include <stdio.h>
int main() {
int myInt;
myInt = 0xFFFFFFE2;
printf("%d\n",myInt);
return 0;
}
That should yield an output of -30. Try it out if you like.
With two's complement it's true that a MSB of 1 indicates a negative number. But the remaining bits are not the binary representation of its value. On the other hand, if the MSB is 0 the remaining bits represent the binary value. But it cannot be said that the number is positive then. Zero is neither positive nor negative.
This picture helped me to understand the principle when I started to learn that there are more representations of numbers than with 0..9:
0
-1 000 1
111 001
-2 110 010 2
101 011
-3 100 3
-4

Calculate Java Int Overflow

Is there a formula to calculate what the overflow of a Java int would be?
Example: if I add 1 to Integer.MAX_VALUE; the answer is not 2147483648, but rather -2147483648.
Question: if I wanted to calculate what Java would print for a value larger than 2^32, is there an easy mathematical expression (theoretical, not in code)?
((x + 231) mod 232) - 231
Is this what you're looking for? That should be the result of any mathematical operation on a machine that uses 32-bit signed 2's complement integers. That is, if the mathematical value of an operation returns x, the above formula gives the integer that would actually be stored (if the operation doesn't fault, and it's not a "saturating" operation).
Note that I'm using "mod" with a mathematical definition, not the way the % operator works in Java or C. That is, A mod B, where A and B are integers and B > 0, always returns an integer in the range 0 .. B-1, e.g. (-1) mod 5 = 4. More specifically, A mod B = A - B*floor(A/B).
In java an int is 32 bits but it is also signed, which means that the first bit is the "negative" sign. 1 means negative and 0 means positive. Because of this, the largest number is 2147483647 (0111 1111 1111 1111 1111 1111 1111 1111). If you add 1 it makes it 1000 0000 0000 0000 0000 0000 0000 0000 which translates to -2147483648. For any values larger than that you would need to use a long
I believe this would work:
int expected = ((val + Integer.MAX_VALUE) % Integer.MAX_VALUE) - Integer.MAX_VALUE;

how 128 int after narrow casting to byte becomes -128

i know in java Byte has 8 bit memory , that is from -128 to 127. I also know the concept of narrowing casting. and int lost some precision. But can some one help me understand the following
public class PrimitiveTypes {
public static void main(String[] args) {
Byte byteVar= (byte) 128;
System.out.println(byteVar);
}
}
o/p is -128
please dont tell me because of cycle of 127 it shows -128 .
I need the binary arithmatic that happened here.
What i able to find from net is java stores integer in 2's complements which is used to store negative no.
so from 2's complement
128 becomes 10000000
after flipping 11111111
and adding 1 bit will be
10000000
Question is how this 10000000
becomes -128?
ANS :
Thanks all i got my ans:
I need to convert 2's complement no 10000000 to decimal like
you first check if the number is negative or positive by looking at the sign bit. If it is positive, simply convert it to decimal. If it is negative, make it positive by inverting the bits and adding one. Then, convert the result to decimal. The negative of this number is the value of the original binary.
Interpret 11011011 as a two's complement binary number, and give its decimal equivalent.
First, note that the number is negative, since it starts with a 1.
Change the sign to get the magnitude of the number.
1 1 0 1 1 0 1 1
¬ 0 0 1 0 0 1 0 0
+ 1
0 0 1 0 0 1 0 1
Convert the magnitude to decimal: 001001012 = 25_16 = 2×16 + 5 = 37_10.
Since the original number was negative, the final result is -37.
So in my case
10000000
becomes
01111111
adding 1 will be
10000000
which is 128
and original no was negative since the first bit is 1
so -128
In binary the int 128 looks like this.
0000 0000 0000 0000 0000 0000 1000 0000
This is 32 bits, 4 bytes.
When you type cast it to byte you get the last 8 binary digits.
1000 0000
And this turns out to be the binary representation of the byte -128.
So the result is -128 indeed.
All the byte values in binary go like this:
1000 0000 -> - 128
1000 0001 -> - 127
1000 0010 -> - 126
...
1111 1110 -> -2
1111 1111 -> -1
0000 0000 -> 0
0000 0001 -> 1
0000 0010 -> 2
...
0111 1110 -> 126
0111 1111 -> 127
This should make it clear to you.
Your confusion is probably because you're thinking of
1000 0000 as an unsigned byte value. In Java there are
no unsigned bytes. The 1st bit determines the sign.
If there were unsigned bytes (as in some other languages),
this binary value would be indeed 128 and not -128.

Categories