使用Integer.parseInt转换32位二进制字符串失败

时间:2012-01-17 02:25:29

标签: java integer 32-bit parseint numberformatexception

为什么这部分代码失败:

Integer.parseInt("11000000000000000000000000000000",2);

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

据我所知,Integer是32位值。上面代码中的0和1的数量是32.如果有31个代码可以工作。为什么会这样?

4 个答案:

答案 0 :(得分:16)

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

带符号的int是二进制补码表示中的32位值,其中第一位表示数字的符号,剩余的31位表示数字的值。 (-ish。)Java只支持有符号整数,而parseInt()和朋友不应该解析两个补码位模式 - 从而解释1或(可能隐含的)0 at从右边第32个位置作为标志。它们旨在支持解析人类可读的表达,这是一个可选的-(或+)符号,后跟数字的绝对值。

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

特殊套管两个基地的力量也感觉很奇怪。最好有一个单独的方法来处理位模式,例如this answer中的那个。

答案 1 :(得分:4)

根据docs,整数的最大值为2^31-1。其中,二进制是:

1111111111111111111111111111111

换句话说,31 1连续。

答案 2 :(得分:2)

这是因为Integer.parseInt“11000000000000000000000000000000”不是-1073741824的二进制补码表示,而是一个不适合int值的正值3221225472,范围是-2147483648到2147483647.但我们可以解析二进制补码二进制字符串表示的BigInteger:

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

这给出了预期的-1073741824结果

答案 3 :(得分:0)

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

添加一点点轻松,因为重读这篇文章听起来太迂腐了,我明白Oracle可能并不关心我是否认为这是一个bug。 : - )

您可以尝试:

   long avoidOverflows = Long.parseLong("11000000000000000000000000000000",2);
   int thisShouldBeANegativeNumber = (int)avoidOverflows);
   System.out.println(avoidOverflows + " -> " + thisShouldBeANegativeNumber);
你应该看到了    3221225472 - > -1073741824

您有时必须使用颜色执行此操作,具体取决于它们如何以文本形式存储。

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