将 *binary* 字符串转换为数字时出现 NumberFormatException

Posted

技术标签:

【中文标题】将 *binary* 字符串转换为数字时出现 NumberFormatException【英文标题】:NumberFormatException while converting a *binary* string to a number 【发布时间】:2015-06-03 03:58:55 【问题描述】:

所以我有这个二进制字符串(32 个字符对应 32 位):

 String s = "11111111110000011101110111011000";

当我尝试将其转换为数字时,它会抛出 NumberFormatException:

 Integer.parseInt(s,2);

不知道为什么。任何的想法?奇怪的是,如果我用零位 (0) 替换字符串中从左边 (1) 开始的第一位,那么它就可以工作。第一位只是用来表示数字的符号,所以这里应该不会溢出4个字节吧?

==================

更新问题:感谢大家的回答。我现在明白了;基本上 parseInt() 方法不能处理符号位,它假设符号位只代表任何其他位的值。所以现在的问题是如何将这样的二进制字符串转换为有符号的整数?我知道你们中的一些人建议我使用 long,但在我的情况下,我只需要它是一个 int(很长可以解释,但你可以假设)。

【问题讨论】:

因为它是二进制的,而不是整数。如果是 1011,你会期望 11,但你会得到 1,011 “很长的解释”我明白你在那里做了什么:P 【参考方案1】:

您尝试解析的数字大于2^31-1 (max integer),请改用 Long:

String s = "11111111110000011101110111011000";
System.out.println(Long.parseLong(s, 2)); // 4,290,895,320

如果您想查看 Integer 的最大值是多少:

System.out.println(Integer.MAX_VALUE); // 2,147,483,647

响应您的 UPDATE 部分,如果您不介意丢失信息(当您将 long 转换为 int 时会发生这种情况),您可以这样做:

String s = "11111111110000011101110111011000";
long l = Long.parseLong(s,2);
int i = (int)l;
System.out.println(i); // -4071976

【讨论】:

你能解释一下为什么它大于 2^32 而第一位(左起)仅用于表示数字的符号吗? @Simo 不确定我是否明白了你的要求 - 但我在答案中添加了一部分可以解释它。 嘿阿法辛。得到你的答案。谢谢。关于如何将此类二进制字符串转换为 int(而不是 long)的任何想法。它与我的压缩编码有关,所以长数字对压缩没有帮助。 @Simo 您无法将其转换为 int 而不会丢失信息。如果您可以丢失信息,那么您可以检查s 的长度并删除字符,直到您有一个长度为 30 的字符串(您应该避免长度为 31 的字符串 - 只是为了避免达到 2^31 的边缘情况)。一种方法是如我在上面的附加示例中所述。 他没有丢失信息 - 他有 32 位,并希望将它们解释为有符号整数。【参考方案2】:

正如其他人已经提到的,这个二进制字符串不适合 32 位 singed int。但是,从 Java 8 开始,您可以将其解析为 unsigned int,这非常有效!

String s = "11111111110000011101110111011000";
System.out.println(Integer.parseUnsignedInt(s, 2)); // -4071976

Java 8 中还添加了其他有用的无符号数学方法。

【讨论】:

不错!我不知道这个选项!【参考方案3】:

您正试图将一个 32 位数字解析为一个 Integer,它只能有 31 位和一个符号。 parseInt 无法处理符号位;您需要以+-(或什么都不做)的形式给出标志。你的号码应该是(如果我没有搞砸我的转换)-4071976,如果你把它作为-1111100010001000101000 提供给parseInt可以解析它,但不是 em> 为11111111110000011101110111011000

【讨论】:

知道了。谢谢。现在我的问题是如何将该二进制字符串转换为整数?在我的应用程序中(与编码有关),我需要它是一个 int,所以第一位需要代表符号。 (int)Long.parseLong(s, 2)-4071976 (作为你想要的签名 int,而不是 long)。【参考方案4】:

你说你正在尝试解析二进制字符串

String s = "11111111110000011101110111011000";

但是这个值超出了 Java 整数范围:

整数是 32 位的,对于 Java,范围是 -2,147,483,648 到 2,147,483,647。但是您输入的值超出了范围。所以你得到了例外。

但 long 是 64 位,范围是 –9,223,372,036,854,775,808 到 9,223,372,036,854,775,807。所以你可以使用以下内容:

String s = "11111111110000011101110111011000";
Long.parseLong(s,2);//4290895320

【讨论】:

以上是关于将 *binary* 字符串转换为数字时出现 NumberFormatException的主要内容,如果未能解决你的问题,请参考以下文章

将 oracle 转换为 PostgreSQL 时出现数字溢出

将字符串转换为 int 时出现语法错误

将字符串转换为短 C# 时出现格式异常

尝试将字符串转换为 char[][] 时出现问题

将二进制字符串解析为整数时出现数字格式异常

将字符串转换为 int 时出现语法错误 [重复]