Как создать строку, представляющую Java, как если бы это было 64-разрядное значение без знака - PullRequest
3 голосов
/ 20 октября 2008

Моему компоненту передается длинное значение, которое я позже использую в качестве ключа в кеше. Сам ключ является строковым представлением длинного значения, как если бы оно было 64-разрядным значением без знака. То есть, когда мой компонент передан -2944827264075010823L, мне нужно преобразовать его в строковый ключ "15501916809634540793".

У меня есть решение, но оно кажется грубой силой и меня тошнит. По сути, я конвертирую long в шестнадцатеричное строковое представление (так что -2944827264075010823L становится "d721df34a7ec6cf9") и конвертирую шестнадцатеричную строку в BigInteger:

String longValueAsHexString = convertLongToHexString(longValue);
BigInteger bi = new BigInteger(longValueAsHexString, 16);
String longValueString = bi.toString();

Затем я использую longValueString в качестве ключа в кеше.

Я не могу использовать Long.toString (longValue, 16), потому что он возвращает шестнадцатеричную строку для абсолютного значения с префиксом "-".

Итак, мой convertLongToHexString выглядит так:

long mask = 0x00000000ffffffffL;
long bottomHalf = number & mask;
long upperHalf = (number >> 32) & mask;
String bottomHalfString = Long.toString(bottomHalf, 16);
if (bottomHalfString.length() != 8) {
    String zeroes = "0000000000000000";
    bottomHalfString = zeroes.substring(16-bottomHalfString.length()) + bottomHalfString;
}
return Long.toString(upperHalf,16)+bottomHalfString;

Должен быть более элегантный способ сделать это. Есть предложения?

Ответы [ 4 ]

5 голосов
/ 20 октября 2008

Вот моя реализация. Я реорганизовал его, чтобы иметь функцию, принимающую long и возвращающую строку. : -)

import java.math.BigInteger;

class UInt64Test {
    public static void main(String[] args) {
        for (String arg : args)
            System.out.println(toUnsignedString(Long.parseLong(arg)));
    }

    private static final BigInteger B64 = BigInteger.ZERO.setBit(64);
    public static String toUnsignedString(long num) {
        if (num >= 0)
            return String.valueOf(num);
        return BigInteger.valueOf(num).add(B64).toString();
    }
}
4 голосов
/ 20 октября 2008

Я думаю, что ответ Криса лучше, но вот другой, просто для удовольствия.

public static String longUnsignedString(long l) {
  byte[] bytes = new byte[9];

  for (int i = 1; i < 9; i++) {
     bytes[i] = (byte) ((l >> ((8 - i) * 8)) & 255);
  }

  return (new BigInteger(bytes)).toString();
}
2 голосов
/ 29 мая 2013

Пять лет спустя, но есть реализация, которая не использует BigInteger или байтовые массивы.
Вместо этого он эмулирует беззнаковое деление за один шаг и выгружает остальное в стандартную библиотечную функцию:

public static String unsignedToString(long n) {
    long temp = (n >>> 1) / 5;  // Unsigned divide by 10 and floor
    if (temp == 0)
        return Integer.toString((int)n);  // Single digit
    else
        return Long.toString(temp) + (n - temp * 10);  // Multiple digits
}
1 голос
/ 14 сентября 2011

Битовые реализации:

    byte[] bytes = ByteBuffer.allocate(8).putLong(1023L).array();
    System.out.println(new BigInteger(bytes).toString(2));

С уважением, Алекс

...