Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java8 unsigned arithmetic

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?

like image 910
Jannis Froese Avatar asked Apr 07 '14 04:04

Jannis Froese


2 Answers

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.

like image 64
Sotirios Delimanolis Avatar answered Oct 22 '22 15:10

Sotirios Delimanolis


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++;
}
like image 42
DaoWen Avatar answered Oct 22 '22 15:10

DaoWen