问题
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)
回答1:
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.
回答2:
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 comparelong xandyas if they were unsigned with(x ^ Long.MIN_VALUE) < (y ^ Long.MIN_VALUE)(forintyou can cast tolongand mask with0xffffffffLof 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.
回答3:
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
回答4:
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
来源:https://stackoverflow.com/questions/23259194/why-is-1-plus-31-zeros-not-a-valid-integer-if-bit-flags-are-31-length-plus-one