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.
Related
int i =132;
byte b =(byte)i; System.out.println(b);
Mindboggling. Why is the output -124?
In Java, an int is 32 bits. A byte is 8 bits .
Most primitive types in Java are signed, and byte, short, int, and long are encoded in two's complement. (The char type is unsigned, and the concept of a sign is not applicable to boolean.)
In this number scheme the most significant bit specifies the sign of the number. If more bits are needed, the most significant bit ("MSB") is simply copied to the new MSB.
So if you have byte 255: 11111111
and you want to represent it as an int (32 bits) you simply copy the 1 to the left 24 times.
Now, one way to read a negative two's complement number is to start with the least significant bit, move left until you find the first 1, then invert every bit afterwards. The resulting number is the positive version of that number
For example: 11111111 goes to 00000001 = -1. This is what Java will display as the value.
What you probably want to do is know the unsigned value of the byte.
You can accomplish this with a bitmask that deletes everything but the least significant 8 bits. (0xff)
So:
byte signedByte = -1;
int unsignedByte = signedByte & (0xff);
System.out.println("Signed: " + signedByte + " Unsigned: " + unsignedByte);
Would print out: "Signed: -1 Unsigned: 255"
What's actually happening here?
We are using bitwise AND to mask all of the extraneous sign bits (the 1's to the left of the least significant 8 bits.)
When an int is converted into a byte, Java chops-off the left-most 24 bits
1111111111111111111111111010101
&
0000000000000000000000001111111
=
0000000000000000000000001010101
Since the 32nd bit is now the sign bit instead of the 8th bit (and we set the sign bit to 0 which is positive), the original 8 bits from the byte are read by Java as a positive value.
132 in digits (base 10) is 1000_0100 in bits (base 2) and Java stores int in 32 bits:
0000_0000_0000_0000_0000_0000_1000_0100
Algorithm for int-to-byte is left-truncate; Algorithm for System.out.println is two's-complement (Two's-complement is if leftmost bit is 1, interpret as negative one's-complement (invert bits) minus-one.); Thus System.out.println(int-to-byte( )) is:
interpret-as( if-leftmost-bit-is-1[ negative(invert-bits(minus-one(] left-truncate(0000_0000_0000_0000_0000_0000_1000_0100) [)))] )
=interpret-as( if-leftmost-bit-is-1[ negative(invert-bits(minus-one(] 1000_0100 [)))] )
=interpret-as(negative(invert-bits(minus-one(1000_0100))))
=interpret-as(negative(invert-bits(1000_0011)))
=interpret-as(negative(0111_1100))
=interpret-as(negative(124))
=interpret-as(-124)
=-124 Tada!!!
byte in Java is signed, so it has a range -2^7 to 2^7-1 - ie, -128 to 127.
Since 132 is above 127, you end up wrapping around to 132-256=-124. That is, essentially 256 (2^8) is added or subtracted until it falls into range.
For more information, you may want to read up on two's complement.
132 is outside the range of a byte which is -128 to 127 (Byte.MIN_VALUE to Byte.MAX_VALUE)
Instead the top bit of the 8-bit value is treated as the signed which indicates it is negative in this case. So the number is 132 - 256 = -124.
here is a very mechanical method without the distracting theories:
Convert the number into binary representation (use a calculator ok?)
Only copy the rightmost 8 bits (LSB) and discard the rest.
From the result of step#2, if the leftmost bit is 0, then use a calculator to convert the number to decimal. This is your answer.
Else (if the leftmost bit is 1) your answer is negative. Leave all rightmost zeros and the first non-zero bit unchanged. And reversed the rest, that is, replace 1's by 0's and 0's by 1's. Then use a calculator to convert to decimal and append a negative sign to indicate the value is negative.
This more practical method is in accordance to the much theoretical answers above. So, those still reading those Java books saying to use modulo, this is definitely wrong since the 4 steps I outlined above is definitely not a modulo operation.
Two's complement Equation:
In Java, byte (N=8) and int (N=32) are represented by the 2s-complement shown above.
From the equation, a7 is negative for byte but positive for int.
coef: a7 a6 a5 a4 a3 a2 a1 a0
Binary: 1 0 0 0 0 1 0 0
----------------------------------------------
int: 128 + 0 + 0 + 0 + 0 + 4 + 0 + 0 = 132
byte: -128 + 0 + 0 + 0 + 0 + 4 + 0 + 0 = -124
often in books you will find the explanation of casting from int to byte as being performed by modulus division. this is not strictly correct as shown below
what actually happens is the 24 most significant bits from the binary value of the int number are discarded leaving confusion if the remaining leftmost bit is set which designates the number as negative
public class castingsample{
public static void main(String args[]){
int i;
byte y;
i = 1024;
for(i = 1024; i > 0; i-- ){
y = (byte)i;
System.out.print(i + " mod 128 = " + i%128 + " also ");
System.out.println(i + " cast to byte " + " = " + y);
}
}
}
A quick algorithm that simulates the way that it work is the following:
public int toByte(int number) {
int tmp = number & 0xff
return (tmp & 0x80) == 0 ? tmp : tmp - 256;
}
How this work ? Look to daixtr answer. A implementation of exact algorithm discribed in his answer is the following:
public static int toByte(int number) {
int tmp = number & 0xff;
if ((tmp & 0x80) == 0x80) {
int bit = 1;
int mask = 0;
for(;;) {
mask |= bit;
if ((tmp & bit) == 0) {
bit <<=1;
continue;
}
int left = tmp & (~mask);
int right = tmp & mask;
left = ~left;
left &= (~mask);
tmp = left | right;
tmp = -(tmp & 0xff);
break;
}
}
return tmp;
}
If you want to understand this mathematically, like how this works
so basically numbers b/w -128 to 127 will be written same as their decimal value, above that its (your number - 256).
eg. 132, the answer will be
132 - 256 = - 124
i.e.
256 + your answer in the number
256 + (-124) is 132
Another Example
double a = 295.04;
int b = 300;
byte c = (byte) a;
byte d = (byte) b; System.out.println(c + " " + d);
the Output will be 39 44
(295 - 256) (300 - 256)
NOTE: it won't consider numbers after the decimal.
Conceptually, repeated subtractions of 256 are made to your number, until it is in the range -128 to +127. So in your case, you start with 132, then end up with -124 in one step.
Computationally, this corresponds to extracting the 8 least significant bits from your original number. (And note that the most significant bit of these 8 becomes the sign bit.)
Note that in other languages this behaviour is not defined (e.g. C and C++).
In java int takes 4 bytes=4x8=32 bits
byte = 8 bits range=-128 to 127
converting 'int' into 'byte' is like fitting big object into small box
if sign in -ve takes 2's complement
example 1: let number be 130
step 1:130 interms of bits =1000 0010
step 2:condider 1st 7 bits and 8th bit is sign(1=-ve and =+ve)
step 3:convert 1st 7 bits to 2's compliment
000 0010
-------------
111 1101
add 1
-------------
111 1110 =126
step 4:8th bit is "1" hence the sign is -ve
step 5:byte of 130=-126
Example2: let number be 500
step 1:500 interms of bits 0001 1111 0100
step 2:consider 1st 7 bits =111 0100
step 3: the remained bits are '11' gives -ve sign
step 4: take 2's compliment
111 0100
-------------
000 1011
add 1
-------------
000 1100 =12
step 5:byte of 500=-12
example 3: number=300
300=1 0010 1100
1st 7 bits =010 1100
remaining bit is '0' sign =+ve need not take 2's compliment for +ve sign
hence 010 1100 =44
byte(300) =44
N is input number
case 1: 0<=N<=127 answer=N;
case 2: 128<=N<=256 answer=N-256
case 3: N>256
temp1=N/256;
temp2=N-temp*256;
if temp2<=127 then answer=temp2;
else if temp2>=128 then answer=temp2-256;
case 4: negative number input
do same procedure.just change the sign of the solution
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.
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