在Java中,如何将两个长字符比较为无符号?
我将无符号64位数字的位模式存储在在Java中,如何将两个长字符比较为无符号?,java,bit-manipulation,math,Java,Bit Manipulation,Math,我将无符号64位数字的位模式存储在long变量中,并希望计算无符号范围内两个数字之间的距离。因为Java将long解释为2的补码有符号整数,所以我不能只执行a-b,如下例所示: // on the unsigned range, these numbers would be adjacent long a = 0x7fffffffffffffffL; long b = 0x8000000000000000L; // but as two's complement (or any represe
long
变量中,并希望计算无符号范围内两个数字之间的距离。因为Java将long
解释为2的补码有符号整数,所以我不能只执行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;
做这件事的正确方法是什么?当算术结束时,你给出的情况也是如此。如果您将结果解释为无符号值,则在所有情况下都是如此-您只是在更改位模式的解释,它仍然是一个与Ζ264同态的集合。如果您处理的是加法和减法,则无论您使用的是有符号类型还是无符号类型,只要参数都是有符号的或都是无符号的。如果需要比较a和b,请将a-b与0进行比较。适用于我:
long a = 0x7fffffffffffffffL;
long b = 0x8000000000000000L;
b - a = (long) 1
a - b = (long) -1
显然你需要处理比特
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
}
静态布尔比较(长a、长b)
{
如果((a&(Long.MAX_值+1))!=0)
返回值(b&(Long.MAX_值+1))!=0
?(a
或者你可以这样对半做
public static long unsignedDiff(long a, long b) {
long mask = 0xFFFFFFFFL;
return (( ((a >> 32) & mask) - ((b >> 32) & mask) ) << 32) +
+ ((a & mask) - (b & mask));
}
public static long unsignedDiff(长a、长b){
长掩码=0xFFFFFFFFL;
return(((a>>32)和mask)-((b>>32)和mask))如前所述,减法不会有问题,所以如果这就是您要做的全部,那么不要担心
但是,根据您的示例,加法将溢出,并且没有一个关系运算符能够正常工作。如果这是一个问题,那么您可以编写自己的关系操作,或者使用比Long更好的box类型
解决方案:
1.使用BigInteger而不是Long。是为进行大数值计算而创建的,可以轻松支持128位计算
编写您自己的关系运算,并排除可能使用的加法或乘法。编写您自己的关系运算符并不是那么难。首先比较最高有效位。如果两个数字的最高有效位相同,您可以通过按位and(&)来屏蔽它使用0x7FFFFFFFFFFFFFFFFF,然后比较屏蔽值
我使用以下代码:
static boolean unsignedLessThan(long left, long right) {
return (left < right) ^ (left < 0) ^ (right < 0);
}
static boolean unsignedLessThan(长左、长右){
返回(左<右)^(左<0)^(右<0);
}
(基于Tamutnefert的示例)我使用了以下解决方案:
if (longA == longB) return 0;
return (longA < longB) ^ (longA < 0) ^ (longB< 0) ? 1 : -1;
if(longA==longB)返回0;
返回(longA
从Java 8开始,可以通过以下方式将长
作为无符号整数进行比较
以下是Java 7及更早版本的简单后端口:
public static int compareUnsigned(long x, long y) {
return Long.compare(x + Long.MIN_VALUE, y + Long.MIN_VALUE);
}
darksleep提供的解决方法是将有符号类型强制转换为使用两倍字节的类型,例如,使用short(2字节)来保存无符号字节,或使用int(4字节)来保存无符号short。但是,Java没有内置的16字节数字类型,OP可以用来存储无符号long(8字节)正如下面几张海报所指出的那样,我的示例实际上是有效的。我从应用程序中更复杂的代码中提取了它,而没有在事后进行测试,后来发现原始代码中存在另一个错误,这使我相信二进制表示就是问题所在。这意味着这个问题没有多大意义再也没有了。但是,这些答案对我很有帮助,所以我就不谈了。我想我记得有一个答案,它以二进制形式显示了我以后如何使用计算出的差值通过b=a+d
来检索b,以及为什么出于这个目的,如何解释位模式并不重要。但这个答案是真的呃,不见了,或者我在别的地方看到了。不过,这还是有帮助的完全正确,我在代码中有一个bug,我从上面提取了这个例子。添加和减去是我唯一需要的东西。我存储Delta以后重建它的原始值。@亚当,如果你需要比较A和B,比较A -B到0。我不认为这是有效的。为了简单起见,无符号<代码>字节< /Cord> C。比较a=0x80
和b=0x7F
之间的差异。有符号术语a=-128
和b=127
。现在a-b>0
应该是true
如果它们是无符号的,但在Java中它不是有符号的,因为类型byte
是有符号的。@Aravind字节示例不起作用,因为在Java中,字节在重新执行算术。在这种情况下,您将使用(字节)(a-b)A=0x80和b= 0x7f将产生1。如果A是一个小的量值正,B是稍微大的负值,那么-B> 0给出一个肯定的答案,如果你把输入当作签名,这是正确的。但是,如果我们认为它们都是无符号的,那么B实际上是一个大正数,而A -B>0应该是一个大正数。false。@AdamCrume只有在检查a和b是否相等时,您的答案才部分正确。常见的比较情况要复杂得多,如下面的一些答案所示。在比较静态布尔比较(长a,长b)之前,将无符号空间[0,2^64-1]映射到有符号空间[2^63,2^63-1]就足够了{返回一个^0x80000000000000L
Long。比较(a^0x80000000000000L,b^0x80000000000000L)
也可以工作