【问题标题】:Converting Hex in Java, wrong value with negative values在 Java 中转换十六进制,错误的值带有负值
【发布时间】:2017-02-16 06:49:31
【问题描述】:

我已经看到关于主题中提到的主题的几个问题(例如this one),但在我看来,他们都没有提供这个例子。我正在使用 Java7,我想将代表十六进制或十进制的 String 转换为 IntegerLong 值(取决于它所代表的内容),我执行以下操作:

public Number getIntegerOrLong(String num) {
    try {
        return Integer.decode(num);
    } catch (NumberFormatException nf1) {
        final long decodedLong = Long.decode(num);
        if ((int) decodedLong == decodedLong) {//used in Java8 java.util.Math.toIntExact()
            return (int) decodedLong;
        }
        return decodedLong;
    }
}

当我使用表示十进制数的字符串时,一切正常,问题出在负十六进制数

现在,如果我这样做:

String hex = "0x"+Integer.toHexString(Integer.MIN_VALUE);
Object number = getIntegerOrLong(hex);
assertTrue(number instanceof Integer):

失败,因为它返回Long。其他负整数值也一样。

此外,当我使用Long.MIN_VALUE 时,如下所示:

String hex = "0x"+Integer.toHexString(Long.MIN_VALUE);
Object number = getIntegerOrLong(hex);
assertTrue(number instanceof Long):

失败,因为NumberFormatException 带有消息:

java.lang.NumberFormatException: For input string: "8000000000000000"

我还尝试了其他随机 Long 值(因此在 Long.MIN_VALUE 和 Long.MAX_VALUE 内,当我有负数时它也会失败。例如

StringLong 数字 -4,543,669,698,155,229,815 的十六进制 0xc0f1a47ba0c04d89 返回:

java.lang.NumberFormatException: For input string: "c0f1a47ba0c04d89"

如何修复脚本以获得所需的行为?

【问题讨论】:

  • @Aaron,对不起,打字不好。我做"0x"+Integer.toHexString(Integer.MIN_VALUE)。这也很糟糕吗?

标签: java hex decimal


【解决方案1】:

Long.decodeInteger.decode 不接受诸如 Integer.toHexString 返回的补码值:符号应表示为前导 -,如 javadoc 中的 DecodableString 语法所述。

在可选符号和/或基数说明符(“0x”、“0X”、“#”或前导零)之后的字符序列被 Long.parseLong 方法解析为具有指示的基数(10、16 , 或 8)。此字符序列必须表示正值,否则将引发 NumberFormatException。如果指定字符串的第一个字符是减号,则结果取反

如果您可以更改输入String 的格式,则使用Integer.toString(value, 16) 而不是Integer.toHexString(value) 生成它。

如果您可以切换到 Java 8,请使用 parseUnsignedInt/Long

【讨论】:

  • 我无法返回 BigInteger 以获得向后兼容性。对于演员表,我在输入的示例中犯了一个错误,实际上我在做"0x"+Integer.toHexString(Integer.MIN_VALUE)"0x"+Long.toHexString(Long.MIN_VALUE)
  • 我不确定你到底在暗示什么。例如,如果您执行Long.parseUnsignedLong(Long.toString(Long.MIN_VALUE, 16), 16),您仍然会得到一个异常,即java.lang.NumberFormatException: Illegal leading minus sign on unsigned string -8000000000000000
  • 我可以确认Long.parseUnsignedLong(Long.toHexString(Long.MIN_VALUE), 16) 有效(以及Integer 对应)
  • 前导符号应符合Long/Int.decode 中描述的语法:对于十六进制表示,它可以是Signopt 0x HexDigits,即-0x8000000000000000
猜你喜欢
  • 2011-11-26
  • 2023-01-16
  • 2013-04-14
  • 2018-12-06
  • 1970-01-01
  • 2015-03-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多