How to convert Java long to * unsigned * base-x string (and return)?

[editor] I don't accept any answers involving BigInteger or other similar inefficient methods Please read the questions before answering!

Annoyingly, Java does not support unsigned numeric types You can convert byte, short, or int to unsigned using the next larger type, for example:

short s = -10;
int unsigned_short = s & 0xFFFF;

But you can't do this for long because there's no bigger type

So, how to convert a signed long to "unsigned" base-x, which in my case is base-36, and then return? The long class has these methods, but treats long as signed just because they are

I can use some operations and BigInteger to do this, but BigInteger is very slow and creates garbage through temporary BigInteger I can do a lot of conversions (I think) I need one with long The default implementation of toString (long I, int radius) is as efficient as the algorithm

Trying to adjust long Tostring() code, let me:

final int RADIX = 36;
final char[] DIGITS = { '0',...,'Z' };
long value = 100;
if (value == 0) {
    return "0";
} else {
    char[] buf = new char[13];
    int charPos = 12;
    long i = value;
    while (i != 0) {
        buf[charPos--] = DIGITS[Math.abs((int) (i % RADIX))];
        i /= RADIX;
    }
    return new String(buf,charPos + 1,(12 - charPos));
}

But it doesn't handle negative values correctly, even though math abs().

Once this works, I need reverse conversion, but I hope it will be easier You are welcome to put it in your answer

[editor] actually, I only watched long Parselong (string s, int radius), which looks better than long ToString (long I, int radius) is more complex

Solution

long l = 0xffffffffffffffffL; // any long,e.g. -1
long l = 0xffffffffffffffffL; // any long,e.g. -1

    // to string
    BigInteger bi = new BigInteger(Long.toString(l & ~(1L << 63)));
    if (l < 0) bi = bi.setBit(64);
    final String b36 = bi.toString(36);
    System.out.println("original long:" + l);
    System.out.println("result 36: " + b36);

    // parse
    final BigInteger parsedBi = new BigInteger(b36,36);

    l = parsedBi.longValue();
    if (parsedBi.testBit(64)) l = l | (1L << 63);
    System.out.println("parsed long = " + l);

Benchmark (one million operations):

// toString
    long l = 0x0ffffffffffffeffL;
    {
        final long start = System.currentTimeMillis();
        for (int i = 0; i < 1000000; i++) toStringBi(l);
        System.out.println("BigInteger time = " + 
            (System.currentTimeMillis() - start) + " ms.");
    }
    {
        final long start = System.currentTimeMillis();
        for (int i = 0; i < 1000000; i++) Long.toString(l,36);
        System.out.println("Long.toString time = " + 
           (System.currentTimeMillis() - start) + "ms.");
    }
    // Parsing
    final String b36 = toStringBi(l);
    final String long36 = Long.toString(l,36);
    {
        final long start = System.currentTimeMillis();
        for (int i = 0; i < 1000000; i++) {
            final BigInteger parsedBi = new BigInteger(b36,36);
            l = parsedBi.longValue();
            if (parsedBi.testBit(64)) l = l | (1L << 63);
        }
        System.out.println("BigInteger.parse time = " 
            + (System.currentTimeMillis() - start) + " ms.");
    }
    {
        final long start = System.currentTimeMillis();
        for (int i = 0; i < 1000000; i++) Long.parseLong(long36,36);
        System.out.println("Long.parseLong time = " 
            + (System.currentTimeMillis() - start) + "ms.");
    }

>BigInteger time = 1027 Ms. > long ToString time = 244ms. > BigInteger. parse time = 297 ms.> Long. parseLong time = 132ms.

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>