Unsigned long in Java

67,008

Solution 1

In Java 8, unsigned long support was introduced. Still, these are typical longs, but the sign doesn't affect adding and subtracting. For dividing and comparing, you have dedicated methods in Long. Also, you can do the following:

long l1 = Long.parseUnsignedLong("12345678901234567890");
String l1Str = Long.toUnsignedString(l1)

BigInteger is a bit different. It can keep huge numbers. It stores them as int[] and supports arithmetic.

Solution 2

Although Java has no unsigned long type, you can treat signed 64-bit two's-complement integers (i.e. long values) as unsigned if you are careful about it.

Many primitive integer operations are sign agnostic for two's-complement representations. For example, you can use Java primitive addition, subtraction and multiplication on an unsigned number represented as a long, and get the "right" answer.

For other operations such as division and comparison, the Long class provides method like divideUnsigned and compareUnsigned that will give the correct results for unsigned numbers represented as long values.

The Long methods supporting unsigned operations were added in Java 8. Prior to that, you could use 3rd-party libraries to achieve the same effect. For example, the static methods in the Guava UnsignedLongs class.


Is BigInteger the signed long that Java supports?

BigInteger would be another way to represent integer values greater that Long.MAX_VALUE. But BigInteger is a heavy-weight class. It is unnecessary if your numbers all fall within the range 0 to 264 - 1 (inclusive).

Solution 3

If using a third party library is an option, there is jOOU (a spin off library from jOOQ), which offers wrapper types for unsigned integer numbers in Java. That's not exactly the same thing as having primitive type (and thus byte code) support for unsigned types, but perhaps it's still good enough for your use-case.

import static org.joou.Unsigned.*;

// and then...
UByte    b = ubyte(1);
UShort   s = ushort(1);
UInteger i = uint(1);
ULong    l = ulong(1);

All of these types extend java.lang.Number and can be converted into higher-order primitive types and BigInteger. In your case, earlier versions of jOOU simply stored the unsigned long value in a BigInteger. Version 0.9.3 does some cool bit shifting to fit the value in an ordinary long.

(Disclaimer: I work for the company behind these libraries)

Share:
67,008

Related videos on Youtube

Annapoorni D
Author by

Annapoorni D

Updated on September 29, 2021

Comments

  • Annapoorni D
    Annapoorni D over 2 years

    Currently, I am using signed values, -2^63 to 2^63-1. Now I need the same range (2 * 2^64), but with positive values only. I found the java documentations mentioning unsigned long, which suits this use.

    I tried to declare 2^64 to a Long wrapper object, but it still loses the data, in other words, it only captures till the Long.MAX_VALUE, so I am clearly missing something. Is BigInteger the signed long that Java supports?

    Is there a definition or pointer as to how to declare and use it?

    • Juvanis
      Juvanis almost 7 years
      BigInteger is the way to go.
    • President James K. Polk
      President James K. Polk almost 7 years
      Java only supports signed longs. Period. However, even an if there was such a thing as an unsigned long, 2^64 is too big to fit in it.
    • harold
      harold almost 7 years
      There is no unsigned long, but depending on the situation you may get away with treating a long as unsigned.
    • xenteros
      xenteros almost 7 years
      There is unsigned long
    • soorapadman
      soorapadman almost 7 years