Java中的双大于号(>>)是什么?

43

>>符号在Java中是位运算符之一。它表示右移操作,将一个数的二进制位向右移动指定的位数。


我们刚刚不是有一个关于 >> 和 >>> 的问题吗? - Michael Myers
2
如果你喜欢双数,那你肯定会喜欢三倍数。请访问 https://dev59.com/dnNA5IYBdhLWcg3wQ7Yw 查看详情。 - akf
是的,在谷歌上搜索符号非常烦人;即使加上引号和高级搜索,尝试查找“>>”也没有结果,谷歌就是无视它。 - Da-Jin
如果你在谷歌上搜索符号遇到麻烦,你可以尝试使用这个搜索引擎: http://symbolhound.com/ 它乐意接受符号。 - Jomar Sevillejo
7个回答

76
>> 操作符是按位右移操作符。
简单例子:
int i = 4;
System.out.println(i >> 1); // prints 2 - since shift right is equal to divide by 2
System.out.println(i << 1); // prints 8 - since shift left is equal to multiply by 2

负数的行为方式相同:

int i = -4;
System.out.println(i >> 1); // prints -2
System.out.println(i << 1); // prints -8

通常来说- i << k 相当于 i*(2^k),而 i >> k 则相当于 i/(2^k)

在所有情况下(就像任何其他算术运算符一样),您应该始终确保不会溢出数据类型。


2
如果您给出一个带有负数的例子,那么您将得到我的点赞。 - Michael Myers
@YuvalAdam 位移操作的目的是什么(这是我一直想知道的),考虑到它等同于*2和/2(或幂次方)? - Richard Tingle
@RichardTingle,这只是另一个您可以使用的运算符。在某些情况下,使用位移操作符是有语义意义的,例如当实际处理位掩码时。 - Yuval Adam
为什么它总是返回整数而不是浮点数?例如:2 >> 2 应该返回 2/(2^2) = 2/4 = 0.5, 但它返回 0。 - nikoloza
所以,他们使用 >> 和 << 而不是 * 和 /?这是一种让新程序员毫无理由地感到困惑的好方法。 - frosty
显示剩余3条评论

38
这是位移运算符。 文档 有符号左移运算符"<<"将一个位模式向左移动,有符号右移运算符">>"将一个位模式向右移动。位模式由左操作数给定,要向右移动的位置数由右操作数给定。无符号右移运算符">>>"将一个零移入最左侧的位置,而">>"后的最左侧位置取决于符号扩展。

1
它也可能发生在关闭嵌套泛型参数时。与C++98不同,Java会尽力以上下文相关的方式有效地解释这两个字符作为单独的符号,而不是强制在两者之间加入空格字符。 - Tom Hawtin - tackline

18

它将位数向左移动...

这里有一些关于Java 运算符的信息。

例如:

101  = 5
Shifting out the right "1"
10 = 2
Shifting the other way...
1010 = 10

7

右移操作:

右移操作符 >> 将数值中的所有位向右移动指定次数。其一般形式为:value >> num。 这里,num 指定要将 value 中的值向右移动的位置数。也就是说,>> 将指定值中的所有位向右移动 num 指定的位数。 以下代码片段将值 32 向右移动两个位置,结果 a 被设置为 8:

int a = 32;
a = a >> 2; // a now contains 8

当一个值的位数被“移出”时,这些位数将会丢失。例如,下面的代码片段将值35向右移动两个位置,这会导致最低位的两个位数丢失,结果a被设为8。

int a = 35;
a = a >> 2; // a still contains 8

从二进制的角度看这个操作,更加清晰地展示了它的实现过程:

00100011 35 >> 2
00001000 8

每次将一个值向右移动,都会将该值除以二并且舍弃任何余数。您可以利用这一点来实现高性能整数除以2。当然,您必须确保没有将任何位移到右端。
在向右移动时,右移所暴露的顶部(最左边)位将使用前面的顶部位的内容填充。这称为符号扩展,可用于在向右移位时保留负数的符号。例如,–8 >> 1–4,在二进制中是:
11111000 –8 >>1
11111100 –4

有趣的是,如果你向右移动-1位,结果总是保持为-1,因为符号扩展会在高位比特中带来更多的1。

有时候,在将值向右移动时,不希望对其进行符号扩展。例如,下面的程序将字节值转换为其十六进制字符串表示形式。请注意,移位后的值通过与0x0f相与进行掩码处理,以丢弃任何符号扩展位,使该值可以用作十六进制字符数组的索引。

// Masking sign extension.
class HexByte {
  static public void main(String args[]) {
    char hex[] = {
      '0', '1', '2', '3', '4', '5', '6', '7',
      '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
    };
  byte b = (byte) 0xf1;
 System.out.println("b = 0x" + hex[(b >> 4) & 0x0f] + hex[b & 0x0f]);
}
}

这是输出结果:
b = 0xf1

5
那是一个右移位操作。

4
非常棒的回答 :D - nutella_eater

1

我相信这是位移运算符。它将所有的 1 和 0 向右移动一位。(我想你可以想象出 << 做什么了...:))


1

正如其他人所指出的那样,这是正确的位移操作。在许多所谓的“C风格”语言中都可以看到它。

关于位移操作的大量详细信息,由你的StackOverflow用户提供,请查看我很久以前发布的一个问题,这个问题帮助我最终理解了它:位移操作的绝对初学者指南。(在那里发布的人非常友善地深入探讨了这个主题,我希望这也能帮助到你。)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接