5

Java 8 is widely reported to have library support for unsigned integers. However, there seem to be no articles explaining how to use it and how much is possible.

Some functions like Integer.CompareUnsigned are easy enough to find and seem to do what one would expect. However, I fail to write even a simple loop that loops over all powers of two within the range of unsigned long.

int i = 0;
for(long l=1; (Long.compareUnsigned(l, Long.MAX_VALUE*2) < 0) && i<100; l+=l) {
    System.out.println(l);
    i++;
}

produces the output

1
2
4
8
...
1152921504606846976
2305843009213693952
4611686018427387904
-9223372036854775808
0
0
0
...
0

Am I missing something or are external libraries still required for this simple task?

Jannis Froese
  • 1,347
  • 2
  • 10
  • 23

2 Answers2

6

If you're referring to

(Long.compareUnsigned(l, Long.MAX_VALUE*2) < 0)

l reaches

-9223372036854775808

unsigned it is

9223372036854775808

and

Long.MAX_VALUE*2

is

18446744073709551614

So l is smaller than Long.MAX_VALUE*2 in the unsigned world.

Assuming you're asking about the 0's

0
0
0
...
0

the problem (if you see it that way) is that, for long (other numerical primitives), the first bit is the sign bit.

so

10000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000

is

-9223372036854775808

When you do

-9223372036854775808 + -9223372036854775808

you underflow (overflow?) since

    10000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
+   10000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000

is

00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000

which is 0. On later loop iterations, 0 + 0 remains 0.

Sotirios Delimanolis
  • 274,122
  • 60
  • 696
  • 724
4

The only problem here is that you're printing l as a signed integer. You can use Integer.toUnsignedString to get the results you're expecting:

int i = 0;
byte[] tmp = new byte[9];
for(int l=1; (Long.compareUnsigned(l, Long.MAX_VALUE*2) < 0) && i<100; l+=l) {
    System.out.println(Integer.toUsignedString(l)); // <== MODIFIED THIS LINE
    i++;
}
DaoWen
  • 32,589
  • 6
  • 74
  • 101
  • Since `l` can never be greater than Long.MAX_VALUE*2, I suspect the loop will never terminate either. – Joachim Isaksson Apr 07 '14 at 04:42
  • 1
    @JoachimIsaksson - There's a `&& i<100` clause in there too. But yeah, I assumed the OP would understand that `int` and `long` aren't the same thing. If not, then Sotirios' answer clarifies that. – DaoWen Apr 07 '14 at 04:46
  • That fixed the output of the last correct number, but after that I still get only 0 – Jannis Froese Apr 07 '14 at 04:51
  • @JoachimIsaksson The int was a copy paste error, l is supposed to be of type long. The i<100 clause guarantees that the loop terminates, since l get's stuck on 0 – Jannis Froese Apr 07 '14 at 04:52
  • @JannisFroese - I think Sotirios did a good job of explaining _why_ your loop bound doesn't work. If you want the loop to stop once `l` overflows the range of an `unsigned long`, why don't you just change it to `for(long l=1; l!=0; l+=l)`? On another note, *you should never use l as a variable name because it looks way too much like a 1!* – DaoWen Apr 07 '14 at 05:16