According to my comprehension, Integer type in Java is 32-bit-signed, the most significant bit is the signed bit. This is why Integer.MAX_VALUE is 2147483647, which is:
1111111111111111111111111111111(1 repeated in 31 times).
So I assume that it actually can be represented as:
01111111111111111111111111111111(a 0 followed by 1 repeated 31 times)
The 0 means this is a positive integer.
Then for the following codes:
int test = -2147483647;
String converted = Integer.toBinaryString(test);
System.out.println(converted);
The output is:
10000000000000000000000000000001
Why the output is like above? For me, the binary stream should be represented as -1, since the most significant bit is 1 means negative.
Like this:
int minusOne = -1;
String converted1 = Integer.toBinaryString(test);
System.out.println(converted1);
The output is the same as above:
10000000000000000000000000000001
Any explanation?
Look at the folowing two snippets, did you find the problem:
int test = -2147483647;
String converted = Integer.toBinaryString(test);
System.out.println(converted);
int minusOne = -1;
String converted1 = Integer.toBinaryString(test);
System.out.println(converted1);
You are printing out the same variable test, that's why the output is the same. If you printout "minusOne" it would be all 1's.
10000000000000000000000000000001 -> -2147483647 = Integer.MIN_VALUE + 1
11111111111111111111111111111111 -> -1
1111111111111111111111111111111 -> Integer.MAX_VALUE = 2147483647
10000000000000000000000000000000 -> Integer.MAX_VALUE + 1
10000000000000000000000000000000 -> Integer.MIN_VALUE = -2147483648
10000000000000000000000000000001 -> Integer.MIN_VALUE + 1
In addition to #dragon66's point, be aware that these are two's complement numbers. They are not represented as sign, magnitude.
In two's complement representation, one negates a number by inverting all the bits, then adding 1. This way, there's only one representation of 0.
Related
This question already has answers here:
Why does the negative of Integer.MIN_VALUE give the same value? [duplicate]
(2 answers)
Why does -INT_MIN = INT_MIN in a signed, two's complement representation?
(9 answers)
Closed 5 years ago.
int a = Integer.MIN_VALUE;
int b = -a;
System.out.println("a = "+a + " | b = "+b);
Result :
a = -2147483648 | b = -2147483648
I was expecting b to be a positive number.
Changing the sign of Integer.MIN_VALUE produces an overflow; you're seeing the result of that.
If you have ever done something like this:
int a = Integer.MAX_VALUE;
a++;
System.out.println(a);
You will know that when something exceeds the data type's max value, it loops back to its min value. And when it is less than the min value, it loops back to the max value.
The same thing happens here.
Negating the min value of int would mathematically give us 2147483648, but since that is one larger than the max value. It loops back to the min value again, which is -2147483648.
Fun fact: negation is basically switching every bit from 0 to 1 and 1 to 0, then adding one. Try doing this to 10000000000000000000000000000000 which is what int's min value looks like in binary.
For the underlying binary explanation, it is because signed Integers are stored with Two's complement.
So, the most negative number in binary is 1000 0000. To inverse the sign, you flip all the bits, and add one so..
1000 0000 => 0111 1111 + 1 = 1000 0000
And you're back where you started!
As in the example above, the signed range of a Byte (8 bits) is −128 to 127, so -(-128) is 128, which is 1 over 127, so it overflows back to -128.
And as for why use Two's complement? 1 - 1 becomes 1 + (-1) or 0001 + 1111 = 0000. So by storing negative numbers in Two's complement, subtraction is done by just takes the Two's complement of the second number and just adding them together. (Which is much more efficient for the machine than adding a subtraction circuit to the the Arithmetic-Logic Unit (ALU); As it already has the bit-wise not and addition to do twos complement).
Usually when we try to assign a value to an int type which is more than the max value of int type it loopbacks again starts from min value of int, e.g.
2147483648 -will become-> -2147483648
2147483649 -will become-> -2147483647
2147483650 -will become-> -2147483646
After first statement value of a is -2147483648
And when you are doing int b = -a; usually b should have
b = -a --> -(-2147483648) --> 2147483648
But max positive value of int is 2147483647 and 2147483648 is one larger than 2147483647 it will loop back by 1 and become -2147483648.
I am multiplying the 2 very large number in java , but the multiply output seems to be little strange
Code
long a = 2539586720l;
long b = 77284752003l;
a*=b;
System.out.println(a);
a=(long)1e12;
b=(long)1e12;
a*=b;
System.out.println(a);
Output:
-6642854965492867616
2003764205206896640
In the first case why the result is negative , if it's because of overflow then how come the result of second is positive ? Please explain this behavior ?
Code
Edit:
I am using mod=100000000009 operation still it's negative ?
a = ((a%mod)*(b%mod))%mod
The result that you get is typically an overflow issue, for a long: java allocates 63 bits for the number and the Most Significant Bit (MSB) for the sign (0 for positive values and 1 for negative values) so 64 bits in total.
So knowing that, Long.MAX_VALUE + 1 equals to -9223372036854775808 because Long.MAX_VALUE = 2^63 - 1 = 9223372036854775807 = 0x7fffffffffffffffL so if we add 1 to it, we get 0x8000000000000000L= Long.MIN_VALUE = -2^63 = -9223372036854775808. In this case the MSB switches from 0 to 1 so the result is negative which is actually what you get in the first use case.
If the MSB is set to 1 and you cause a new overflow with some computation, it will switch to 0 again (because we keep only the first 64 bits) so the result will be positive, which is actually what you get in the second use case.
To avoid that you need to use BigInteger.
Yes. It is an overflow issue. The long size is 8 bytes and the range goes from -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807
If you want to multiply really big numbers. Use BigInteger
import java.math.*;
public static void main(String[] args){
BigInteger bi1, bi2, bi3;
bi1 = new BigInteger("2539586720"); //or 1000000000000
bi2 = new BigInteger("77284752003");
// multiply bi1 with bi2 and assign result to bi3
bi3 = bi1.multiply(bi2);
String str = bi1 + " * " + bi2 + " = " +bi3;
//Multiplication result is 2539586720 * 77284752003 = 196271329845312200160
}
As per JLS 15.17.1
If an integer multiplication overflows, then the result is the low-order bits of the mathematical product as represented in some sufficiently large two's-complement format. As a result, if overflow occurs, then the sign of the result may not be the same as the sign of the mathematical product of the two operand values.
This is why you are getting negative values and doesn't have any correlation with the input numbers. This is because of the fact that long in Java can represent only from -2^63 to (2^63)-1 and your result is greater than this.
In order to avoid this issue, when dealing with large number arithmetic, you should always use BigInteger. A sample code is given below
BigInteger.valueOf(123L).multiply(BigInteger.valueOf(456L));
In regards to the behavior, both are examples are overflows. The fact that one answer is negative does not add any special meaning. The first set of numbers you multipled happen to result in a long whose most significant bit is 1, while the latter set didn't.
I have a simple program:
public class Mathz {
static int i = 1;
public static void main(String[] args) {
while (true){
i = i + i;
System.out.println(i);
}
}
}
When I run this program, all I see is 0 for i in my output. I would have expected the first time round we would have i = 1 + 1, followed by i = 2 + 2, followed by i = 4 + 4 etc.
Is this due to the fact that as soon as we try to re-declare i on the left hand-side, its value gets reset to 0?
If anyone can point me into the finer details of this that would be great.
Change the int to long and it seems to be printing numbers as expected. I'm surprised at how fast it hits the max 32-bit value!
Introduction
The problem is integer overflow. If it overflows, it goes back to the minimum value and continues from there. If it underflows, it goes back to the maximum value and continues from there. The image below is of an Odometer. I use this to explain overflows. It's a mechanical overflow but a good example still.
In an Odometer, the max digit = 9, so going beyond the maximum means 9 + 1, which carries over and gives a 0 ; However there is no higher digit to change to a 1, so the counter resets to zero. You get the idea - "integer overflows" come to mind now.
The largest decimal literal of type int is 2147483647 (231-1). All
decimal literals from 0 to 2147483647 may appear anywhere an int
literal may appear, but the literal 2147483648 may appear only as the
operand of the unary negation operator -.
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.
Thus, 2147483647 + 1 overflows and wraps around to -2147483648. Hence int i=2147483647 + 1 would be overflowed, which isn't equal to 2147483648. Also, you say "it always prints 0". It does not, because http://ideone.com/WHrQIW. Below, these 8 numbers show the point at which it pivots and overflows. It then starts to print 0s. Also, don't be surprised how fast it calculates, the machines of today are rapid.
268435456
536870912
1073741824
-2147483648
0
0
0
0
Why integer overflow "wraps around"
Original PDF
The issue is due to integer overflow.
In 32-bit twos-complement arithmetic:
i does indeed start out having power-of-two values, but then overflow behaviors start once you get to 230:
230 + 230 = -231
-231 + -231 = 0
...in int arithmetic, since it's essentially arithmetic mod 2^32.
No, it does not print only zeros.
Change it to this and you will see what happens.
int k = 50;
while (true){
i = i + i;
System.out.println(i);
k--;
if (k<0) break;
}
What happens is called overflow.
static int i = 1;
public static void main(String[] args) throws InterruptedException {
while (true){
i = i + i;
System.out.println(i);
Thread.sleep(100);
}
}
out put:
2
4
8
16
32
64
...
1073741824
-2147483648
0
0
when sum > Integer.MAX_INT then assign i = 0;
Since I don't have enough reputation I cannot post the picture of the output for the same program in C with controlled output, u can try yourself and see that it actually prints 32 times and then as explained due to overflow i=1073741824 + 1073741824 changes to
-2147483648 and one more further addition is out of range of int and turns to Zero .
#include<stdio.h>
#include<conio.h>
int main()
{
static int i = 1;
while (true){
i = i + i;
printf("\n%d",i);
_getch();
}
return 0;
}
The value of i is stored in memory using a fixed quantity of binary digits. When a number needs more digits than are available, only the lowest digits are stored (the highest digits get lost).
Adding i to itself is the same as multiplying i by two. Just like multiplying a number by ten in decimal notation can be performed by sliding each digit to the left and putting a zero on the right, multiplying a number by two in binary notation can be performed the same way. This adds one digit on the right, so a digit gets lost on the left.
Here the starting value is 1, so if we use 8 digits to store i (for example),
after 0 iterations, the value is 00000001
after 1 iteration , the value is 00000010
after 2 iterations, the value is 00000100
and so on, until the final non-zero step
after 7 iterations, the value is 10000000
after 8 iterations, the value is 00000000
No matter how many binary digits are allocated to store the number, and no matter what the starting value is, eventually all of the digits will be lost as they are pushed off to the left. After that point, continuing to double the number will not change the number - it will still be represented by all zeroes.
It is correct, but after 31 iterations, 1073741824 + 1073741824 doesn't calculate correctly (overflows) and after that prints only 0.
You can refactor to use BigInteger, so your infinite loop will work correctly.
public class Mathz {
static BigInteger i = new BigInteger("1");
public static void main(String[] args) {
while (true){
i = i.add(i);
System.out.println(i);
}
}
}
For debugging such cases it is good to reduce the number of iterations in the loop. Use this instead of your while(true):
for(int r = 0; r<100; r++)
You can then see that it starts with 2 and is doubling the value until it is causing an overflow.
I'll use an 8-bit number for illustration because it can be completely detailed in a short space. Hex numbers begin with 0x, while binary numbers begin with 0b.
The max value for an 8-bit unsigned integer is 255 (0xFF or 0b11111111).
If you add 1, you would typically expect to get: 256 (0x100 or 0b100000000).
But since that's too many bits (9), that's over the max, so the first part just gets dropped, leaving you with 0 effectively (0x(1)00 or 0b(1)00000000, but with the 1 dropped).
So when your program runs, you get:
1 = 0x01 = 0b1
2 = 0x02 = 0b10
4 = 0x04 = 0b100
8 = 0x08 = 0b1000
16 = 0x10 = 0b10000
32 = 0x20 = 0b100000
64 = 0x40 = 0b1000000
128 = 0x80 = 0b10000000
256 = 0x00 = 0b00000000 (wraps to 0)
0 + 0 = 0 = 0x00 = 0b00000000
0 + 0 = 0 = 0x00 = 0b00000000
0 + 0 = 0 = 0x00 = 0b00000000
...
The largest decimal literal of type int is 2147483648 (=231). All decimal literals from 0 to 2147483647 may appear anywhere an int literal may appear, but the literal 2147483648 may appear only as the operand of the unary negation operator -.
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.
According to this, in the around-fourth paragraph below the first table, says
In general, we will use an integer to represent a set on a domain of up to 32 values (or 64, using a 64-bit integer), with a 1 bit representing a member that is present and a 0 bit one that is absent.
If that's true, then why does this 32 digit binary number exceed Integer.MAX_VALUE?
System.out.println(Integer.parseInt("10000000000000000000000000000000", 2));
Error:
Exception in thread "main" java.lang.NumberFormatException: For input string:
"10000000000000000000000000000000"
at java.lang.NumberFormatException.forInputString(Unknown Source)
at java.lang.Integer.parseInt(Unknown Source)
at Test.main(Test.java:10)
In base 2, 10000000000000000000000000000000 (that's 31 zeroes) is 2^31. A Java int is a 32-bit twos complement representation of numbers between -2^31 and 2^31-1; and this range of course does not include 2^31. That's why this value can't be converted to an int - although a long would be fine.
If you have a Java int whose bits are 10000000000000000000000000000000 (still 31 zeroes), that's -2^31.
It's not true that the first bit of a Java int is a positive/negative flag. It's simply a digit with place value of -2^31.
It exceeds Integer.MAX_VALUE because it really does exceed Integer.MAX_VALUE. It's Integer.MAX_VALUE + 1, which you can absolutely calculate in int-space and you can write it down as 0x80000000 or as Integer.MIN_VALUE, but it'll be negative.
Which is why parseInt complains.
You just can't parse it that way - you can absolutely represent a bitvector with the 32nd bit set with an int. The "sign bit" (which is a misleading name, but we seem to be stuck with it) is just a normal bit like any other bit. Its special meaning only comes into play for:
converting to/from String
converting to a wider or floating point type
division and remainder
right shift, see >> vs >>>
comparisons except equality, for example 1 > 0x80000000. You can compare long x and y as if they were unsigned with (x ^ Long.MIN_VALUE) < (y ^ Long.MIN_VALUE) (for int you can cast to long and mask with 0xffffffffL of course)
The "sign bit" is just an other bit without special meaning for:
addition and subtraction
bitwise operations (including left shift)
multiplication
equality testing
converting to a narrower type
If you're interpreting your int as a bitvector, the "sign bit" will just be a normal bit, but you must take care that all the operations you do on it agree on that.
Original answer:
I figured it out. This webpage cleared it up for me:
Java integers are 32 bits. The highest bit is reserved for plus or minus sign. So you can set/unset 31 one-bit flags
My misunderstanding was that bit flags used the 32nd bit in an integer in this way, as the negative or positive marker, as if it were an option to do so. But Java defines an integer that way, so it's not an option--it's a result or by-product of that definition. An integer has only 31 bits that represent the number itself. The 32nd serves as the plus-minus.
(After writing this, I can see that it makes no sense to even say "bit flags use" anything. Bit flags are concept, the integer is a concrete type.)
Update: Some observations:
Integer.MIN_VALUE equals -2147483648, which in binary, is
10000000000000000000000000000000
The first bit indicates negative. It's a sign bit in this situation because this is a signed integer (Integer.MIN_VALUE is negative, and min-and-max are equidistant to zero). Were it an unsigned integer, it would just be another value-bit.
http://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html:
Signed:
int: By default, the int data type is a 32-bit signed two's complement integer, which has a minimum value of -231 and a maximum value of 231-1.
Unsigned:
In Java SE 8 and later, you can use the int data type to represent an unsigned 32-bit integer, which has a minimum value of 0 and a maximum value of 232-1. Use the Integer class to use int data type as an unsigned integer. See the section The Number Classes for more information. Static methods like compareUnsigned, divideUnsigned etc have been added to the Integer class to support the arithmetic operations for unsigned integers.
Again: Integer.MIN_VALUE equals -2147483648, which in binary, is
10000000000000000000000000000000
Changing that "sign bit" to a zero does not make this 2147483648 (Integer.MAX_VALUE). It makes it
00000000000000000000000000000000
which is zero. Integer.MAX_VALUE in binary is
01111111111111111111111111111111
Switching the "sign bit" to a one doesn't make it MIN_VALUE.
11111111111111111111111111111111
Attempting to parse this fails, because 32 bits are too large for the value portion of a signed integer:
System.out.println(Integer.parseInt("10000000000000000000000000000000", 2));
Error:
Exception in thread "main" java.lang.NumberFormatException: For input string:
"10000000000000000000000000000000"
at java.lang.NumberFormatException.forInputString(Unknown Source)
at java.lang.Integer.parseInt(Unknown Source)
at Test.main(Test.java:10)
Rather
11111111111111111111111111111111
is
1111111111111111111111111111111
with a "sign bit" indicating negative. A binary digit with thirty-two ones is -1. I can't get my mind around why at the moment. I also don't know how to parse a negative (signed) binary. This
Integer.parseInt("-1111111111111111111111111111111", 2)
is equal to
num: -2147483647
10000000000000000000000000000001
So it's overflowing or something...
Testing class:
public class BinaryNumberTest {
public static final void main(String[] ignored) {
testNum(Integer.parseInt("-1111111111111111111111111111111", 2), "-1111111111111111111111111111111");
testNum(Integer.MAX_VALUE, "Integer.MAX_VALUE");
testNum(0, "0");
testNum(Integer.MIN_VALUE, "Integer.MIN_VALUE");
}
private static final void testNum(int num, String description) {
System.out.println(description + ": " + num);
System.out.println();
int numMinus1 = num - 1;
System.out.println(" num-1: " + numMinus1);
System.out.println(" " + get32BitZeroPaddedBinaryNum(numMinus1));
System.out.println(" num: " + num);
System.out.println(" " + get32BitZeroPaddedBinaryNum(num));
int numPlus1 = num + 1;
System.out.println(" num+1: " + numPlus1);
System.out.println(" " + get32BitZeroPaddedBinaryNum(numPlus1));
System.out.println();
}
private static final String get32BitZeroPaddedBinaryNum(int num) {
return String.format("%32s", Integer.toBinaryString(num)).replace(' ', '0');
}
}
Output:
-1111111111111111111111111111111: -2147483647
num-1: -2147483648
10000000000000000000000000000000
num: -2147483647
10000000000000000000000000000001
num+1: -2147483646
10000000000000000000000000000010
Integer.MAX_VALUE: 2147483647
num-1: 2147483646
01111111111111111111111111111110
num: 2147483647
01111111111111111111111111111111
num+1: -2147483648
10000000000000000000000000000000
0: 0
num-1: -1
11111111111111111111111111111111
num: 0
00000000000000000000000000000000
num+1: 1
00000000000000000000000000000001
Integer.MIN_VALUE: -2147483648
num-1: 2147483647
01111111111111111111111111111111
num: -2147483648
10000000000000000000000000000000
num+1: -2147483647
10000000000000000000000000000001
When you use Integer.parseInt, you must explicitly determine the sign of the converting value. So if its Integer.MIN_VALUE, for parseInt it looks like this:
Integer.parseInt("-10000000000000000000000000000000", 2);
— still 32 bits, but with minus as prefix. If no sign is used, the first bit ("sign bit") will be zero (positive value) by default and you will not be able to convert value that consists of more than 31 bits that's why you NumberFormatException — Integer.MAX_VALUE is 01111111111111111111111111111111
Or you may use Integer.parseUnsignedInt :
Integer.parseUnsignedInt("10000000000000000000000000000000", 2);
Here the binary value will be converted "as is" and the first bit will be interpreted as a sign bit. The result in both cases is -2^31
I am missing something while determining how Java stores and retrieves integers. I have the following code
public class Test1 {
public static void main(String args[]) {
int a = 100;
int negateA = (a | 0x80000000);
System.out.println("Negative A: " + negateA);
System.out.println("Negative A in HEX: " + Integer.toHexString(negateA));
}
}
Output:
Negative A: -2147483548
Negative A in HEX: 80000064
From the output, the value in HEX makes sense to me as I am setting the most significant bit of the integer and the rest of the value indicates its decimal value to be 100 which is what I 've set it initially.
I fail to understand why when I print just the integer I get -2147483548
Is there a difference between how java stores the number internally and when its retrieved?
This is not how you obtain a negative number from a positive number! Java uses two's complement.
In order to invert the sign of an int (whether it is initally positive or negative), you do:
~val + 1
Same for longs, bytes and shorts.
The only number for which it doesn't work is 0x80000000, ie Integer.MIN_VALUE, ie -2^31. But that is one of the characteristics of an n-bit two's complement representation: it can represent numbers ranging from -2^(n-1) up to 2^(n-1) - 1.
Let's take 1 as an example:
0x00000001 // i = 1
0xFFFFFFFE // ~i
0xFFFFFFFF // ~i + 1 == -1
0xFFFFFFFF // i = -1
0x00000000 // ~i
0x00000001 // ~i + 1 == 1
The difference is not between "how it is stored" and "when it is retrieved", but it boils down to how the internal representation is interpreted when you convert to decimal and binary. In the first case it is interpreted as twos-complement, which yields your negative number. When you convert it to hex using Integer.toHexString, it is intepreted as an unsigned value. From the javadoc of Integer.toHexString:
The unsigned integer value is the argument plus 23^2 if the argument is
negative; otherwise, it is equal to the argument