查看下面的Java示例,将二进制字符串中的负整数转换回整数类型。
String binary = Integer.toBinaryString(-1); // convert -1 to binary
// 11111111 11111111 11111111 11111111 (two's complement)
int number = Integer.parseInt(binary, 2); // convert negative binary back to integer
System.out.println(number); // output ??
结果是NumberFormatException
!
Exception in thread "main" java.lang.NumberFormatException: For input string: "11111111111111111111111111111111" under radix 2
at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:68)
at java.base/java.lang.Integer.parseInt(Integer.java:652)
at com.mkyong.crypto.bytes.Byte2.main(Byte2.java:17)
NumberFormatException
是由于溢出造成的,字符串11111111111111111111111111111111
(长度为32)无法放入32位int
类型吗?
注意
整数的值是-2^31
到2^31-1
,而不是2^32-1
。
1.整数溢出?
在Java中, int
是32位二进制补码整数,最左边的第一位或最高有效位表示数字的符号,0为正,1为负。
{1}1111111 11111111 11111111 11111111 = {1} = most significant bit, denote positive or negative
由于最左边的位保留给数字的符号,因此Java int
32位仅具有-2^31 (-2,147,483,648)
到2^31-1 (2,147,483,647)
。
System.out.println(Integer.MIN_VALUE); // -2,147,483,648 , -2^31
System.out.println(Integer.MAX_VALUE); // 2,147,483,647 , 2^31-1
再次检查二进制字符串,即完整的32位2^32-1 (4,294,967,295)
。 int
类型无法处理这么大的数字,并且Java不支持unsigned int
。
11111111 11111111 11111111 11111111
2.长
为了解决这个问题,我们可以使用long
64位二进制补码整数,其值从-2^63
到2^63-1
。
String binary = Integer.toBinaryString(-1);
//int number = Integer.parseInt(binary, 2);
long l = Long.parseLong(binary, 2); // 11111111 11111111 11111111 11111111
int number = (int) l;
System.out.println(number); // -1
3. Java 8
对于Java 8,它引入了支持unsigned
操作的新API,请尝试Integer.parseUnsignedInt()
。
String binary = Integer.toBinaryString(-1);
//int number = Integer.parseInt(binary, 2);
int number = Integer.parseUnsignedInt(binary, 2);
System.out.println(number); // -1
参考文献
翻译自: https://mkyong.com/java/java-convert-negative-binary-to-integer/