12

为什么这部分代码会失败:

Integer.parseInt("11000000000000000000000000000000",2);

Exception in thread "main" java.lang.NumberFormatException: For input string: "11000000000000000000000000000000"

据我了解,整数是一个 32 位值。上面代码中的 0 和 1 的数量是 32。如果有 31,则代码有效。为什么呢?

4

4 回答 4

17

您的代码失败,因为它试图解析一个需要 33 位才能存储为有符号整数的数字。

有符号int是二进制补码表示的 32 位值,其中第一位表示数字的符号,其余 31 位表示数字的值。(-ish。)Java 仅支持有符号整数,parseInt()并且朋友不应该解析二进制补码位模式 - 因此将右侧第 32 位的1或(可能暗示)解释为符号。0它们旨在支持解析人类可读的表示,这是符号的可选-(或+),后跟数字的绝对值。

在这种情况下,这是一种错误的直觉,导致您期望您描述的行为:如果您正在解析除基数 2 之外的任何其他基数(或者可能是其他常用的二次幂基数),您会期望第一个数字影响符号的输入?显然你不会;比如说,按设计parseInt("2147483648")返回将是 PHP 级别的疯狂。-2147483648

特殊外壳的二次幂基地也感觉很奇怪。最好有一种单独的方法来处理位模式,例如这个答案中的那个。

于 2012-01-17T02:28:56.483 回答
4

根据文档,整数的最大值是2^31-1. 其中,二进制是:

1111111111111111111111111111111

换句话说,1连续 31 个。

于 2012-01-17T02:31:17.870 回答
2

这是因为对于 Integer.parseInt "110000000000000000000000000000000" 不是 -1073741824 的二进制补码表示,而是正值 3221225472,它不适合 int 值范围 -2147483648 到 2147483647。但我们可以解析二进制补码表示:BigInteger

int i = new BigInteger("11000000000000000000000000000000", 2).intValue()

这给出了预期的 -1073741824 结果

于 2013-08-29T10:54:47.723 回答
0

即使您的字符串“11 .....很多零”是负整数的合法二进制表示, Integer.parseInt() 也会失败。我认为这是一个错误。

添加一点轻浮,因为重读这篇文章听起来太迂腐了,我知道甲骨文可能并不在乎我是否认为这是一个错误。:-)

你可以试试:

   long avoidOverflows = Long.parseLong("11000000000000000000000000000000",2);
   int thisShouldBeANegativeNumber = (int)avoidOverflows);
   System.out.println(avoidOverflows + " -> " + thisShouldBeANegativeNumber);

你应该看到
3221225472 -> -1073741824

您有时必须对颜色执行此操作,具体取决于它们作为文本存储的方式。

顺便说一句,如果您正在解析十六进制表示并且您正在解析像“88888888”这样的负数,则可能会发生确切的事情。您需要使用 Long.parseLong() 然后进行转换。

于 2012-01-17T02:51:12.353 回答