Integer.valueOf(String, int radix)
and Integer.parseInt(String, int radix)
只会解析值 -2 147 483 648 到 2 147 483 647 的数字,即 32 位有符号整数的值。
这些函数无法将二进制补码解释为二进制 (radix = 2
),因为传递的字符串可以是任意长度,因此前导 1 可以是数字或符号位的一部分。我猜 Java 开发人员认为最合乎逻辑的处理方式是永远不接受二进制补码,而不是假设第 32 位是符号位。
他们将您的输入二进制字符串读取为无符号 3 549 763 730(大于最大 int 值)。要读取负值,您需要给出一个正二进制数-
在前面签名。例如对于-5
:
Integer.parseInt("1011", 2); // 11
// Even if you extended the 1s to try and make two's complement of 5,
// it would always read it as a positive binary value
Integer.parseInt("-101", 2); // -5, this is right
解决方案:
我建议,首先,如果您可以将其存储为正数,并自行添加额外的符号信息(例如-
符号),这样做。例如:
String binString;
if(i < 0)
binString = "-" + Integer.toBinaryString(-i);
else // positive i
binString = Integer.toBinaryString(i);
如果您需要使用有符号的二进制字符串,为了以二进制补码形式(作为字符串)获取负数并将其解析为 int,我建议您手动获取补码,将其转换为 int,然后更正标志。回想一下,二进制补码 = 二进制补码 + 1,而二进制补码只是将每一位取反。
作为示例实现:
String binString = "11010011100101010001100010010010";
StringBuilder onesComplementBuilder = new StringBuilder();
for(char bit : binString.toCharArray()) {
// if bit is '0', append a 1. if bit is '1', append a 0.
onesComplementBuilder.append((bit == '0') ? 1 : 0);
}
String onesComplement = onesComplementBuilder.toString();
System.out.println(onesComplement); // should be the NOT of binString
int converted = Integer.valueOf(onesComplement, 2);
// two's complement = one's complement + 1. This is the positive value
// of our original binary string, so make it negative again.
int value = -(converted + 1);
您也可以编写自己的版本Integer.parseInt
对于 32 位二进制补码。当然,这是假设您没有使用 Java 8 并且不能只使用Integer.parseUnsignedInt
,@llogiq 在我打字时指出的。
编辑:你也可以使用Long.parseLong(String, 2)
首先,然后计算二进制补码(并用 0xFFFFFFFF 屏蔽它),然后降级long
向下int
。写得更快,代码可能也更快。