Java - 将无符号十六进制字符串解析为带符号长整型

19

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

  d1bc4f7154ac9edb

请问"-3333702275990511909"的十六进制值是多少?如果你使用Long.toHexString("d1bc4f7154ac9edb"),也会得到相同的结果。

目前,我们只假设我只能访问十六进制字符串值。

  Long.parseLong(hexstring, 16);

无法正常工作,因为它将其转换为一个对于Long类型来说太大的不同值。有没有一种方法可以将这些无符号十六进制值转换为有符号的long类型?

谢谢!

4个回答

22
您可以使用 BigInteger 来解析它并返回一个 long:
long value = new BigInteger("d1bc4f7154ac9edb", 16).longValue();
System.out.println(value); // this outputs -3333702275990511909

6
对于现代访问者的一个提示:正如Scott Carey所指出的那样,从Java 8开始,我们可以简单地使用Long.parseUnsignedLong(hexstring, 16)实现,太棒了 :) - NIA

7

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

Long.parseUnsignedLong(hexstring, 16)


该代码用于将十六进制字符串转换为无符号长整型。

6

您可以将其分成两半,每次读取32位。然后使用左移32位和逻辑或运算符将其合并回一个长整型。


2
(Long.parseLong(hexstring.substring(0, 8), 16) << 32) | (Long.parseLong(hexstring.substring(8, 16), 16) << 0) - Knut Forkalsrud

4
以下方法的好处在于每次需要执行此操作时不会创建另一个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?http://docs.oracle.com/javase/7/docs/api/java/lang/Character.html#digit(int,%20int) - asieira
“Character.digit” 包括所有Unicode十进制数字,由于有几组未被恰当记录的数字,我不想处理它们所有。 - Olathe
我认为能够提取任何可能的Unicode数字的数值是一种优势,可以使您的代码更具可移植性和国际化友好性。 即使您的项目不需要它,也许 Stack Overflow 用户会受益于您更新答案。 这只是我的个人意见。 - asieira

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接