javalong-integerbiginteger

How to convert an "unsigned" long to BigInteger


If I have a Java long value - say x - which should be interpreted as an unsigned value (i.e. 0x8000_0000_0000_0000 and higher should be interpreted as positive value) then how can I convert it to BigInteger?

Obviously, BigInteger.valueOf(x) would result in a negative value, and conversion to hexadecimals or bytes seems wasteful.


Solution

  • Actually, the conversion is pretty simple. You can use masking similar to converting unsigned integers to long:


    Let's first create the mask as constant (this simply results in the least significant 32 bits set to 1):

    private static final long UNSIGNED_INT_MASK = (1L << Integer.SIZE) - 1L;
    

    then we can perform:

    int unsignedInt = 0x8000_0000; // sample input value
    long l = (long) unsignedInt & UNSIGNED_INT_MASK;
    

    So for BigInteger we can create the mask like this (64 least significant bits set to 1):

    // use "import static java.math.BigInteger.ONE;" to shorten this line
    private static final BigInteger UNSIGNED_LONG_MASK = BigInteger.ONE.shiftLeft(Long.SIZE).subtract(BigInteger.ONE);
    

    great, then the rest will be easy:

    long unsignedLong = 0x8000_0000_0000_0000L; // sample input value
    BigInteger bi =  BigInteger.valueOf(unsignedLong).and(UNSIGNED_LONG_MASK);
    

    It's not rocket science, but sometimes you just want to find a quick and easy answer.