Java中无符号右移运算符">>>"的目的是什么?

Tyl*_*den 28 java programming-languages bit-manipulation

我理解Java中的无符号右移运算符">>>",但为什么我们需要它,为什么我们不需要相应的无符号左移运算符?

das*_*ght 26

>>>运营商允许你将intlong为32位和64位无符号整型,这是从Java语言缺少的.

当您移动不表示数值的内容时,这非常有用.例如,您可以使用32位ints 表示黑白位图图像,其中每个位图int在屏幕上编码32个像素.如果你需要向右滚动图像,你会更喜欢左边的位int变为零,这样你就可以轻松地从相邻的ints中放置位:

 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;
 }
Run Code Online (Sandbox Code Playgroud)

上面的代码没有注意高三位的内容,因为>>>运算符会产生它们

没有相应的<<运算符,因为有符号和无符号数据类型的左移操作是相同的.

  • @TylerDurden没有``>>>(例如,当你使用``>>)一个32位或64位值的最显著位(又名"符号位")获得特殊待遇 - 它得到复制移位后的新符号位,所以`>>`移位后的值的符号保持不变.对于具有它们的语言中的无符号类型(例如,C/C++或C#),这是不同的.在这些语言中,符号位的内容由第一个操作数的类型控制.由于Java中没有无符号类型,因此该语言最终为无符号"右移"引入了一个特殊的运算符. (4认同)

Men*_* Lu 13

>>>也是找到两个(大)整数的舍入均值安全有效的方法:

int mid = (low + high) >>> 1;
Run Code Online (Sandbox Code Playgroud)

如果整数highlow接近最大的机器整数,上面的结果是正确的

int mid = (low + high) / 2;
Run Code Online (Sandbox Code Playgroud)

由于溢出可能会得到错误的结果.

这是一个使用示例,修复了一个天真的二进制搜索中的错误.


Old*_*eon 5

>>负数的正常右移将使其保持负数。即符号位将被保留。

符号右移>>>也会移动符号位,并将其替换为零位。

不需要等效的左移,因为只有一个符号位,并且它是最左边的位,因此它仅在右移时产生干扰。

本质上,区别在于一个保留符号位,另一个移入零以替换符号位。

对于正数,它们的作用相同。

有关使用两者的示例>>>>>请参阅BigInteger shiftRight