为了账号安全,请及时绑定邮箱和手机立即绑定

如果 Java 的 parseInt 对于有效的 IEEE-754 二进制文件失败

如果 Java 的 parseInt 对于有效的 IEEE-754 二进制文件失败

BIG阳 2021-06-25 18:00:18
还有一个与此类似的线程,但它不是此的重复,因此请不要将其标记为这样。我有一个通信模拟,它获取测试数据 - 浮点数和整数 - 并将它们转换为二进制字符串,然后通过管道发送它们,并由另一端的侦听器接收它们。然后将它们“解包”并转换回数字。但是,使用 Integer.parseInt() 进行的转换会引发异常,即使消息中的 Binary 显然是正确形成的 IEEE-754 binary32 单精度格式。    float flt = -45732.9287f;    int intFloat = Float.floatToRawIntBits(flt);    String str = Integer.toBinaryString(intFloat);    System.out.println("------- Now do the Reverse -------");    int revint = Integer.parseInt(str, 2);    .... Throws java.lang.NumberFormatException: For input string: "11000111001100101010010011101110"at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)在没有基数的情况下使用 parseInt() 会引发类似的异常:    "int revint = Integer.parseInt(str);" throws an exception too, "java.lang.NumberFormatException: For input string: "11000111001100101010010011101110"at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)".因此,这不仅仅是 Radix 使用问题。使用 Long 和 BigInt 转换回来是不正确的,因为它们是 64 位 IEEE-754 格式,适用于有符号双精度,而不是像浮点这样的有符号单精度数据类型。我有一个解决方案来掩盖 Java 转换方法中的不对称性,但让我觉得不协调的是没有原生 API:    System.out.println("------- Now do the Reverse -------");    int revSign = str.substring(0,1).equals("1") ? -1: 1;    System.out.println("The passed-in sign is:"+revSign);    int revint = Integer.valueOf(str.substring(1), 2);    float revFloat = Float.intBitsToFloat(revint)*revSign;我肯定错过了什么。
查看完整描述

3 回答

?
月关宝盒

TA贡献1772条经验 获得超5个赞

"11000111001100101010010011101110"是一个以 1 开头的 32 位二进制数。这意味着它可以表示int2 的补码中的负数。

但是,Integer.parseInt不希望它的输入是 2 的补码表示。它期望符号用前导表示-,而不是用符号位表示,正如您可以在 Javadoc 中阅读的那样:

int java.lang.Integer.parseInt(String s, int radix) 抛出 NumberFormatException

将字符串参数解析为第二个参数指定的基数中的有符号整数。字符串中的字符必须都是指定基数的数字(由java.lang.Character.digit(char, int)是否返回非负值决定),除了第一个字符可以是ASCII减号'-' ('\u005Cu002D') 表示负值或 ASCII 加号 '+' ('\u005Cu002B') 表示正值。返回结果整数值。

因此,它被视为"11000111001100101010010011101110"超出int类型范围的 32 位正数。

以下可用于重新计算 的值intFloat

// replace the leading 1 with - if it's a sign bit

str = (str.length () == 32 && str.charAt (0) == '1') ? ('-' + str.substring (1)) : str;

int revint = Integer.parseInt(str, 2);

// for negative number, we must compute the 2's complement of the number returned

// by parseInt

if (revint < 0) {

  revint = -1 * (revint + Integer.MAX_VALUE + 1);

}

现在两者intFloat和revint将等于-952982290。


编辑:


Java 确实有您需要的 API,只是您没有使用正确的方法。由于toBinaryString(int i)返回“整数参数的字符串表示作为基数为 2的无符号整数”,您应该使用Integer.parseUnsignedInt(String, int)以恢复传递给的值toBinaryString:


float flt = -45732.9287f;

int intFloat = Float.floatToRawIntBits(flt);

String str = Integer.toBinaryString(intFloat);

System.out.println("------- Now do the Reverse -------");

System.out.println (str);

int revint = Integer.parseUnsignedInt(str, 2);


查看完整回答
反对 回复 2021-06-30
  • 3 回答
  • 0 关注
  • 192 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信