Patricia Shanahan wrote:
....
Seems too simple to be true:
v1 + Long.MIN_VALUE "op" v2 + Long.MIN_VALUE
where "op" is any of the numeric comparison operators.
The idea is to shift the ranges so that zero maps to Long.MIN_VALUE
etc., and the natural comparison order is the right one.
Replying to my own article, yet again, the method is correct, and I
don't think there is a simpler one, but I don't think that is a very
clear explanation. I'm using 32 bit int so that I don't have to type as
many digits, but long works the same way.
Unsigned binary arithmetic and two's complement signed binary arithmetic
agree about the bit pattern that results from adding one to any bit pattern.
In both cases, comparisons treat B as being greater than A if, and only
if, you can obtain B from A by repeated addition of one, without going
through a wrap-around point. At the wrap-around, adding one takes you
from the largest to the smallest value.
They disagree about where the wrap-around point should fall. For
unsigned, 0xffffffff is the largest, and its add-one successor, 0, is
the smallest. For 2's complement, 0x7fffffff, Integer.MAX_VALUE, is the
largest, and its add-one successor, 0x80000000, Integer.MIN_VALUE, is
the smallest.
Adding MIN_VALUE maps the unsigned largest to the 2's complement
largest, and its successor, the unsigned smallest, to the 2's complement
smallest. Getting from A+MIN_VALUE to B+MIN_VALUE by repeated addition
of one goes through the 2's complement wrap around point if, and only
if, getting from A to B by repeated addition of one would go through the
unsigned binary wrap-around point.
Thus the result of a 2's complement signed comparison between
v1+Long.MIN_VALUE and v2+Long.MIN_VALUE, is the same as the result of
the same comparison between v1 and v2 in unsigned long arithmetic.
Patricia