Java 32位无符号整数的反向位

Java 32位无符号整数的反向位,java,bit-manipulation,computer-science,Java,Bit Manipulation,Computer Science,问题是反转32位无符号整数的位(因为Java没有无符号整数,所以我们使用long) 下面是我的代码的两个版本。我有两个顾虑: (1) 为什么我的第一个和第二个解决方案不返回相同的值(正确与否) (2) 我的第一个和第二个解决方案出现了错误,没有得到正确的答案 //reverse(3) returns 0 public static long reverse(long a) { long numBits = 32; long finalResult

问题是反转32位无符号整数的位(因为Java没有无符号整数,所以我们使用long)

下面是我的代码的两个版本。我有两个顾虑:

(1) 为什么我的第一个和第二个解决方案不返回相同的值(正确与否)

(2) 我的第一个和第二个解决方案出现了错误,没有得到正确的答案

    //reverse(3) returns 0
    public static long reverse(long a) {
        long numBits = 32;
        long finalResult = 0;
        for(int i = 0; i < numBits; i++){
            long ithBit = a & (1 << i);
            finalResult = finalResult + ithBit * (1 << (numBits - i - 1));
        }
        return finalResult;
    }
//反向(3)返回0
公共静态长反转(长a){
长numBits=32;
长期最终结果=0;
for(int i=0;ilong ithBit=a&(1在这两个版本中,您都有一个逻辑问题:

ithBit * (1 << (numBits - i - 1));

ithBit*(1在这两个版本中,您都有一个逻辑问题:

ithBit * (1 << (numBits - i - 1));

ithBit*(1让我们在迭代时查看您的值。为了澄清,我们将查看中间值,因此我们将代码更改为:

int n = (1 << (numBits - i - 1));
long m = ithBit * n;
finalResult = finalResult + m;
第一次循环迭代(i=0):

第二次循环迭代(i=1):


如您所见,第一个迭代集
n=1让我们在迭代时查看您的值。为了澄清,我们将查看中间值,因此我们将代码更改为:

int n = (1 << (numBits - i - 1));
long m = ithBit * n;
finalResult = finalResult + m;
第一次循环迭代(i=0):

第二次循环迭代(i=1):


如您所见,两个示例的第一个迭代集
n=1问题是“第i位”不是0或1,而是被屏蔽。在这两种情况下,第31位都是0x8000_0000。在第一种情况下,这是一个int,因此它是负数,当转换为long时,它将保持负数。在第二种情况下,它已经是long,因此它将保持正数。要修复它,使其达到预期效果,请执行以下操作:

 ithBit = (a >>> i) & 1;
顺便说一句,使用
long
是愚蠢的;只要您了解Java中有两种类型的转换,无符号和有符号就没有区别

顺便说一下,这三个例子都很糟糕。如果你在做位操作,你想要速度,对吗?(为什么还要麻烦位?)

这是如何做对的(不是我的,是从我这里偷来的):


a=((a>>>1)&0x55555555)|((a&0x555555)>>2)&0x33333333)|((a&0x33333333)>>4)&0x0F0F0F0F)|((a&0x0F0F0F0F)>>8)&0x00FF00FF)|((a&0x00FF00FF)>>16)|(a两个示例的问题是“第i位”不是0或1,而是被屏蔽。在这两种情况下,第31位都是0x8000_0000。在第一种情况下,这是一个int,因此它是负数,当转换为long时,它将保持负数。在第二种情况下,它已经是long,因此它将保持正数。要修复它,使其达到预期效果,请执行以下操作:

 ithBit = (a >>> i) & 1;
顺便说一句,使用
long
是愚蠢的;只要您了解Java中有两种类型的转换,无符号和有符号就没有区别

顺便说一下,这三个例子都很糟糕。如果你在做位操作,你想要速度,对吗?(为什么还要麻烦位?)

这是如何做对的(不是我的,是从我这里偷来的):

a=((a>>>1)和0x55555555)|((a&0x555555)>>2)和0x33333333)|((a&0x33333333)>>4)和0x0F0F0F)|((a&0x0F0F0F)>>8)和0x00FF00FF)|((a&0x00FF00FF)>>16)|(a)
因为Java没有无符号整数,所以我们使用long

这通常是不必要的,因为除除法和比较外的所有算术运算都会导致中的无符号数和有符号数的相同位模式,java使用。对于后两种运算
Integer.divideUnsigned(int,int)
Integer.compareUnsigned(int,int)

问题是反转32位无符号整数的位

Integer.reverse(int)

,强烈建议花些时间阅读

因为Java没有无符号整数,所以我们使用long

这通常是不必要的,因为除除法和比较外的所有算术运算都会导致中的无符号数和有符号数的相同位模式,java使用。对于后两种运算
Integer.divideUnsigned(int,int)
Integer.compareUnsigned(int,int)

问题是反转32位无符号整数的位

Integer.reverse(int)


,强烈建议您花些时间阅读它们。

事实上,它是2^31,而不是2^32。事实上,它是2^31,而不是2^32。FWIW在32位有符号整数中保留32位无符号整数是完全合法的。它适合。所谓的“符号位”是一个您可以直接使用的普通位。FWIW在32位有符号整数中保留32位无符号整数是完全合法的。它将适合。所谓的“符号位”是一个您可以直接使用的普通位。
ithBit      = 00000000 00000000 00000000 00000010
n           = 01000000 00000000 00000000 00000000
m           = 10000000 00000000 00000000 00000000
finalResult = 00000000 00000000 00000000 00000000
public static long reverse4(long a) {
    long rev = 0;
    for (int i = 0; i < 32; i++, a >>= 1)
        rev = (rev << 1) | (a & 1);
    return rev;
}
 ithBit = (a >>> i) & 1;
a = ((a >>> 1) & 0x55555555) | ((a & 0x55555555) << 1);
a = ((a >>> 2) & 0x33333333) | ((a & 0x33333333) << 2);
a = ((a >>> 4) & 0x0F0F0F0F) | ((a & 0x0F0F0F0F) << 4);
a = ((a >>> 8) & 0x00FF00FF) | ((a & 0x00FF00FF) << 8);
a = ( a >>> 16             ) | ( a               << 16);