How to compare two longs as unsigned in Java?

I store bit patterns of unsigned 64-bit numbers in a long variable and want to calculate the distance between two of them in an unsigned range. Since Java interprets long as a signed integer with two additions, I cannot just do a - b , as shown in the following example:

 // on the unsigned range, these numbers would be adjacent long a = 0x7fffffffffffffffL; long b = 0x8000000000000000L; // but as two complement (or any representation that // stores the sign in the first bit), they aren't assert b - a == 1; 

What is the right way to do this?

+4
source share
10 answers

If you are dealing with addition and subtraction, it does not matter if you use signature types without or without sign, if the arguments are signed or both are unsigned. If you need to compare a and b, compare ab with 0.

+5
source

Like arithmetic wraps around, it works the same for the case you give. If you interpret the result as an unsigned value, this will be true for all cases - you just change the interpretation of the bit pattern, this is also a set homomorphic to & Zeta; 2 64 .

+5
source

Works for me:

 long a = 0x7fffffffffffffffL; long b = 0x8000000000000000L; b - a = (long) 1 a - b = (long) -1 
+2
source

As already mentioned, you will not have a problem with subtraction, so if thatโ€™s all you are trying to do, then donโ€™t worry.

But, for example, the addition will overflow, and not one of the relational operators will work properly. If this is a concern, you can write your own relational operating systems or use a better window type than Long.

Solutions: 1. Use BigInteger instead of Long. BigInteger was created to perform calculations with large numbers and can easily support 128-bit calculations.

  1. Write your own relational operations and eliminate the possibility of using addition or multiplication. Writing your own relational operator is really not that difficult. First you compare the most significant bit. If the most significant bit is the same for both numbers, you can hide it by doing bitwise and (&) with 0X7FFFFFFFFFFFFFFFFF, and then compare the masked values.
+1
source

I am using the following code:

 static boolean unsignedLessThan(long left, long right) { return (left < right) ^ (left < 0) ^ (right < 0); } 

(on the example of Tamutnefret)

+1
source

I used this solution:

 if (longA == longB) return 0; return (longA < longB) ^ (longA < 0) ^ (longB< 0) ? 1 : -1; 

All loans go to this site.

+1
source

Starting in Java 8 , comparing long as unsigned integers can be done using Long.compareUnsigned (x, y) .

Here is a simple backport for Java 7 and earlier:

 public static int compareUnsigned(long x, long y) { return Long.compare(x + Long.MIN_VALUE, y + Long.MIN_VALUE); } 
+1
source

Obviously you need to deal with bits.

 static boolean compare(long a, long b) { if(( a & (Long.MAX_VALUE + 1)) != 0) return ( b & (Long.MAX_VALUE + 1) ) != 0 ? (a < b) //same sign : true; //a is greater b else return ( b & (Long.MAX_VALUE + 1) ) != 0 ? false //b is greater a : a < b; //same sign } 
0
source

Or you can do half and half like this,

 public static long unsignedDiff(long a, long b) { long mask = 0xFFFFFFFFL; return (( ((a >> 32) & mask) - ((b >> 32) & mask) ) << 32) + + ((a & mask) - (b & mask)); } 
0
source

All Articles