我理解 Java 中无符号右移运算符 ">>>" 的作用,但为什么我们需要它呢?而且为什么不需要相应的无符号左移运算符呢?
我理解 Java 中无符号右移运算符 ">>>" 的作用,但为什么我们需要它呢?而且为什么不需要相应的无符号左移运算符呢?
>>>
运算符允许您将int
和long
视为32位和64位的无符号整数类型,这是Java语言中缺少的。int
表示黑白位图图像,其中每个int
编码了屏幕上的32个像素。如果您需要向右滚动图像,则希望int
左侧的位变为零,以便您可以轻松地将相邻int
中的位放入其中。 int shiftBy = 3;
int[] imageRow = ...
int shiftCarry = 0;
// The last shiftBy bits are set to 1, the remaining ones are zero
int mask = (1 << shiftBy)-1;
for (int i = 0 ; i != imageRow.length ; i++) {
// Cut out the shiftBits bits on the right
int nextCarry = imageRow & mask;
// Do the shift, and move in the carry into the freed upper bits
imageRow[i] = (imageRow[i] >>> shiftBy) | (carry << (32-shiftBy));
// Prepare the carry for the next iteration of the loop
carry = nextCarry;
}
上面的代码不关注前三位的内容,因为 >>>
运算符会将它们移除。
因为有符号数据类型和无符号数据类型进行左移操作是相同的,所以没有对应的 <<
运算符。
>>
,而不是带有>>>
的操作符,那么对于32位或64位值的最高有效位(也称为“符号位”)将会得到特殊处理 - 它会在移位之后被复制到新的符号位上,因此在>>
移位后,值的符号保持不变。但这个处理方式对于一些语言中的无符号类型来说是不同的,比如C/C++或C#。在这些语言中,符号位的内容由第一个操作数的类型控制。由于Java中没有无符号类型,所以该语言引入了一个专门的操作符来进行无符号右移操作。 - Sergey Kalinichenko>>>
也是一种安全高效的方法,用于找到两个(大)整数的平均值并四舍五入:
int mid = (low + high) >>> 1;
如果整数high
和low
接近于最大的机器整数,那么上述语句将是正确的,但是
int mid = (low + high) / 2;
由于溢出可能会导致错误的结果。
这里是一个使用示例,修复了一个简单二分查找中的错误。
>>
对于一个负数来说,仍然会保持它是负数。也就是说,符号位将被保留。>>>
也会移动符号位,但用0位替换它。>>
和>>>
的示例,请参见BigInteger shiftRight。BigInteger
为例,它使用整数数组来存储数字。要向右移位,它将使用 >>>
向右移动除最高有效数字外的所有数字。 - OldCurmudgeonvoid processBitsLsbFirst(int n, BitProcessor whatever)
{
while(n != 0)
{
whatever.processBit(n & 1);
n >>>= 1;
}
}
基本上,这与符号位(数字移位)或无符号移位(通常是像素相关的东西)有关。
由于左移不管怎样都不涉及符号位,所以 <<< 和 << 是一样的...
无论如何,我还没有遇到过需要使用 >>> 的人,但我相信他们正在做一些惊人的事情。
正如您刚才看到的,>> 运算符每次移位时都会自动用其先前内容填充高位比特。这保留了值的符号。但有时这是不可取的。例如,如果您要移动的内容不表示数值,则可能不希望发生符号扩展。在这种情况下,当您使用基于像素的值和图形时,通常会想将零移入高位比特,无论其初始值如何。这被称为无符号移位。为了实现这一点,您将使用 java 的无符号右移运算符 >>>,它总是将零移入高位比特。
进一步阅读:
http://henkelmann.eu/2011/02/01/java_the_unsigned_right_shift_operator
<<<
运算符。 - Ted Hopp<<<
和<<
)”。 - Ted Hoppint hiint = 2147483647;
System.out.println("mean hiint+hiint/2 = " + ( (((long)hiint+(long)hiint)))/2);
System.out.println("mean hiint*2/2 = " + ( (((long)hiint*(long)2)))/2);
BigInteger bhiint = BigInteger.valueOf(2147483647);
System.out.println("mean bhiint+bhiint/2 = " + (bhiint.add(bhiint).divide(BigInteger.valueOf(2))));