【问题标题】:Java - parse and unsigned hex string into a signed longJava - 将无符号十六进制字符串解析为有符号长
【发布时间】:2011-08-09 01:51:01
【问题描述】:

我有一堆十六进制字符串,其中一个,例如是:

  d1bc4f7154ac9edb

这是“-3333702275990511909”的十六进制值。这与您执行 Long.toHexString("d1bc4f7154ac9edb"); 时得到的十六进制相同;

现在,让我们假设我只能访问十六进制字符串值,就是这样。这样做:

  Long.parseLong(hexstring, 16);

不起作用,因为它将其转换为对于 Long 来说太大的不同值。是否可以将这些无符号十六进制值转换为有符号长整数?

谢谢!

【问题讨论】:

    标签: java hex long-integer


    【解决方案1】:

    您可以使用BigInteger 对其进行解析并取回long

    long value = new BigInteger("d1bc4f7154ac9edb", 16).longValue();
    System.out.println(value); // this outputs -3333702275990511909
    

    【讨论】:

    • 给现代访问者的注意事项:正如 Scott Carey 所说,从 Java 8 开始,我们可以简单地使用 Long.parseUnsignedLong(hexstring, 16),太酷了 :)
    【解决方案2】:

    您可以将其分成两半,一次读取 32 位。 然后使用 shift-left by 32 和一个逻辑 or 将其恢复为一个 long。

    【讨论】:

    • 大致类似于:(Long.parseLong(hexstring.substring(0, 8), 16)
    【解决方案3】:

    以下方法的好处是每次您需要执行此操作时都不会创建另一个 BigInteger 对象。

    public class Test {
      /**
       * Returns a {@code long} containing the least-significant 64 bits of the unsigned hexadecimal input.
       * 
       * @param  valueInUnsignedHex     a {@link String} containing the value in unsigned hexadecimal notation
       * @return                        a {@code long} containing the least-significant 64 bits of the value
       * @throws NumberFormatException  if the input {@link String} is empty or contains any nonhexadecimal characters
       */
      public static final long fromUnsignedHex(final String valueInUnsignedHex) {
        long value = 0;
    
        final int hexLength = valueInUnsignedHex.length();
        if (hexLength == 0) throw new NumberFormatException("For input string: \"\"");
        for (int i = Math.max(0, hexLength - 16); i < hexLength; i++) {
          final char ch = valueInUnsignedHex.charAt(i);
    
          if      (ch >= '0' && ch <= '9') value = (value << 4) | (ch - '0'         );
          else if (ch >= 'A' && ch <= 'F') value = (value << 4) | (ch - ('A' - 0xaL));
          else if (ch >= 'a' && ch <= 'f') value = (value << 4) | (ch - ('a' - 0xaL));
          else                             throw new NumberFormatException("For input string: \"" + valueInUnsignedHex + "\"");
        }
    
        return value;
      }
    
      public static void main(String[] args) {
        System.out.println(fromUnsignedHex("d1bc4f7154ac9edb"));
      }
    }
    

    这会产生

    -3333702275990511909
    

    【讨论】:

    • 这看起来不错,但不是像上面那样获取数字值,也许最好使用 Character.digit? docs.oracle.com/javase/7/docs/api/java/lang/…
    • Character.digit 包括所有 Unicode 十进制数字,我不想处理所有这些数字,因为它们有好几组,其中一些没有正确记录。
    • 我相信能够提取任何可能的 Unicode 数字的数值是一个加分项,因为它可以使您的代码更加可移植和国际化友好。即使您的项目不需要它,如果您更新答案,堆栈溢出用户可能会受益。只是我的 2 美分。
    【解决方案4】:

    之前的答案过于复杂或过时。

    Long.parseUnsignedLong(hexstring, 16)

    【讨论】:

      猜你喜欢
      • 2017-01-11
      • 2013-03-22
      • 1970-01-01
      • 2023-04-11
      • 2015-11-23
      • 2011-08-21
      • 2013-04-15
      • 2017-05-30
      • 1970-01-01
      相关资源
      最近更新 更多