我在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;
这样做的正确方法是什么?
答案 0 :(得分:5)
当算术包围时,对于你给出的情况,它的效果相同。如果将结果解释为无符号值,则对于所有情况都是如此 - 您只是更改位模式的解释,它仍然是与 Ζ 2 64 的
答案 1 :(得分:3)
如果你正在处理加法和减法,那么无论你是使用有符号类型还是无符号类型都没关系,只要这些参数都是有符号的或者都是无符号的。如果您需要比较a和b,请将a-b与0进行比较。
答案 2 :(得分:2)
适合我:
long a = 0x7fffffffffffffffL;
long b = 0x8000000000000000L;
b - a = (long) 1
a - b = (long) -1
答案 3 :(得分:2)
我使用了这个解决方案:
if (longA == longB) return 0;
return (longA < longB) ^ (longA < 0) ^ (longB< 0) ? 1 : -1;
答案 4 :(得分:2)
从 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);
}
答案 5 :(得分:1)
如前所述,你不会有减法问题,所以如果这就是你要做的全部,那么别担心。
但是,通过您的示例,添加将溢出,并且任何关系运算符都不会正常工作。如果这是一个问题,那么你可以编写自己的关系操作,或使用比Long更好的盒子类型。
解决方案: 1.使用BigInteger而不是Long。 BigInteger是为了进行大数计算而创建的,可以轻松支持128位计算。
答案 6 :(得分:1)
我使用以下代码:
static boolean unsignedLessThan(long left, long right) {
return (left < right) ^ (left < 0) ^ (right < 0);
}
(基于Tamutnefret的例子)
答案 7 :(得分:0)
答案 8 :(得分:0)
显然你需要处理比特。
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
}
答案 9 :(得分:0)
或者你可以这样做一半,
public static long unsignedDiff(long a, long b) {
long mask = 0xFFFFFFFFL;
return (( ((a >> 32) & mask) - ((b >> 32) & mask) ) << 32) +
+ ((a & mask) - (b & mask));
}