2008-10-20 6 views
3

Mon composant reçoit une valeur longue que j'utiliserai plus tard comme clé dans un cache. La clé elle-même est une représentation sous forme de chaîne de la valeur longue comme si elle était une valeur 64 bits non signée. C'est-à-dire, quand mon composant est remis -2944827264075010823L, j'ai besoin de convertir cela en la clé de chaîne "15501916809634540793".Comment créer une chaîne représentant un Java long comme s'il était non signé Valeur 64 bits

J'ai une solution, mais il semble que la force brute et cela me rend un peu mal à l'aise. Essentiellement, je convertir long en une représentation de chaîne hexadécimale (si -2944827264075010823L devient « d721df34a7ec6cf9 ») et convertir la chaîne hexadécimale en BigInteger:

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

J'utilise ensuite longValueString comme la clé dans le cache.

Je ne peux pas utiliser Long.toString (longValue, 16), car il renvoie la chaîne hexadécimale pour la valeur absolue, précédée d'un "-".

Alors mon convertLongToHexString ressemble à ceci:

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; 

Il doit y avoir une façon plus élégante de le faire. Aucune suggestion?

+0

Vous pouvez utiliser Long.toHexString() au lieu de votre convertLongToHexString –

Répondre

5

Voici ma mise en œuvre. Je l'ai refactorisé pour avoir une fonction prenant un long et renvoyant une chaîne. :-)

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

Je pense que la réponse de Chris est meilleure, mais en voici une autre juste pour s'amuser.

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(); 
} 
1

implémentations Bitless:

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

salutations, Alex

2

Cinq ans de retard, mais voici une implémentation qui n'utilise pas des tableaux BigInteger ou octet.
, il émule lieu la division non signée pour une étape et déleste le reste à la fonction de la bibliothèque standard:

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 
} 
Questions connexes