我在 long 变量中存储无符号64位数字的位模式,并希望计算无符号范围内两个数字之间的距离。因为Java将 long 解释为二进制补码有符号整数,所以我不能只执行 a - b ,如下例所示:

// on the unsigned range, these numbers would be adjacent
long a = 0x7fffffffffffffffL;
long b = 0x8000000000000000L;

// but as two's complement (or any representation that 
// stores the sign in the first bit), they aren't
assert b - a == 1;

这样做的正确方法是什么?

有帮助吗?

解决方案

如果您正在处理加法和减法,那么无论您使用的是有符号类型还是无符号类型都无关紧要,只要这些参数都是有符号的或两者都是无符号的。如果您需要比较a和b,请将a-b与0进行比较。

其他提示

当算术包围时,对于你给出的情况,它的效果相同。如果将结果解释为无符号值,则对于所有情况都是如此 - 您只是更改位模式的解释,它仍然是与 Ζ 的集同态2 64

适合我:

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

我使用了这个解决方案:

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

所有积分都会转到此网站

Java 8 开始, long 与无符号整数的比较可以通过 Long.compareUnsigned(x,y)

这是Java 7及更早版本的简单backport:

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

如前所述,你不会有减法问题,所以如果这就是你要做的全部,那么别担心。

但是,通过您的示例,添加将溢出,并且任何关系运算符都不会正常工作。如果这是一个问题,那么你可以编写自己的关系操作,或使用比Long更好的盒子类型。

解决方案: 1.使用BigInteger而不是Long。 BigInteger 是为进行大型计算而创建的数字,可以轻松支持128位计算。

  1. 编写您自己的关系操作,并将添加或乘法的使用排除在外。编写自己的关系运算符真的不是那么难。首先,您比较最重要的位。如果两个数字的最高有效位相同,则可以通过按位和(&amp;)使用0X7FFFFFFFFFFFFFFF进行屏蔽,然后比较屏蔽值。

我使用以下代码:

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

(基于Tamutnefret的例子)

显然你需要处理比特。

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
}

或者你可以这样做一半,

public static long unsignedDiff(long a, long b) {
    long mask = 0xFFFFFFFFL;
    return (( ((a >> 32) & mask) - ((b >> 32) & mask) ) << 32) +
       + ((a & mask) - (b & mask));
}
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top