>>>和>>之间的区别


Answers:


408

>> 是算术右移, >>>是逻辑右移。

在算术移位中,将扩展符号位以保留数字的符号性。

例如:用8位表示的-2将是11111110(因为最高有效位的权重为负)。使用算术移位将其右移一位,您将得到11111111-1。但是,逻辑上的右移并不关心该值是否可能表示带符号的数字;它只是将所有内容移至右侧,并从左侧填充0。使用逻辑移位将-2右移一位将得到01111111


8
我同意并赞赏算术移位用于将带符号的数字乘以2^k,但我发现这是每个人的答案,这很奇怪。一串位不是数字,并且>>始终可以在任何位串上使用:不管位串在其中扮演什么角色,以及是否具有“符号”的概念,它始终会执行相同的操作。可以通过讨论您的操作数被解释为带正负号的情况来扩展已经很好的答案吗?我的投诉有意义吗?
Ziggy

11
为什么说一串比特不是数字?您会说一个十进制数字序列不是数字吗?
danben 2014年

4
@danben只有将数字链接到上下文时,才可以讨论数字是不是。如果互联网只是电力,那么我同意字符串只是一个数字。
bvdb 2015年

1
@danben,但实际上,我认为Ziggy真正指的是(imho),String也可以将a视为a char[]。他不是说a char不是数字;他只是说这是一个无符号数字。我认为那是他迷路的地方。
bvdb 2015年

5
@Ziggy是正确的:并非每个比特串都是一个数字,也不是每个十进制数字序列都是一个数字。例如:电话号码,邮政编码(在许多国家/地区)等都是十进制数字的字符串,但是对它们进行加,减或乘运算没有意义,因此它们并不是数字。它们碰巧是十进制数字的字符串,但应视为字符串。(加拿大和英国的
邮政编码

102

>>>无符号移位;它将插入0。>>被签名,并将扩展符号位。

JLS 15.19移位运算符

移位运算符包括左移位<<,有符号右移位>>和无符号右移位>>>

的值n>>s是带符号扩展名的n右移位。s

的值n>>>s零扩展的n右移位s位置。

    System.out.println(Integer.toBinaryString(-1));
    // prints "11111111111111111111111111111111"
    System.out.println(Integer.toBinaryString(-1 >> 16));
    // prints "11111111111111111111111111111111"
    System.out.println(Integer.toBinaryString(-1 >>> 16));
    // prints "1111111111111111"

为了使事情更清楚,增加积极的对应

System.out.println(Integer.toBinaryString(121));
// prints "1111001"
System.out.println(Integer.toBinaryString(121 >> 1));
// prints "111100"
System.out.println(Integer.toBinaryString(121 >>> 1));
// prints "111100"

由于它为正,有符号和无符号移位都将在最左边的位加0。

相关问题


没有您的示例,我将无法理解。
mr5

47

他们都是右移,但>>>unsigned

文档中

无符号右移运算符“ >>>”将零移位到最左位置,而“ >>”之后的最左位置取决于符号扩展名。


12
你能用一个例子来解释吗
Kasun Siyambalapitiya'Sep

1
我也认为您应该举一个例子。
byxor

我想那>>>是未签名的,但是为什么7>>32=7呢?我运行了一个循环,一次执行一次换班,然后看到32换班后又回到了7。唯一有意义的方法是,对于每个移出的数字,它都会进入一个“外圈”。之后32的变化,它在某种程度上达到了回到它的位置,但显然仍没有意义。到底是怎么回事?
伊恩·利玛塔

@IanLimarta不是吗?我只得到0。(for (int i = 7 << 1, j = 0; j < 32; j++) System.out.println(Integer.toString(i >>= 1, 2));)如果您要说为什么>>32它本身返回原始值,请参见this
Moira

对不起。我的意思是为什么'7 >>> 32 = 7'。
伊恩·利玛塔

40

逻辑右移(v >>> n)返回一个值,其中in的位v已向右移了n位的位置,而0从左侧移入了。考虑以二进制形式移位8位值:

01111111 >>> 2 = 00011111
10000000 >>> 2 = 00100000

如果我们将这些位解释为无符号非负整数,则逻辑右移具有将数字除以2的相应幂的作用。但是,如果数字以二进制补码表示,则逻辑右移不能正确地划分负数。例如,当这些位被解释为无符号数字时,第二个右移将移位128到32。但是,如Java中常见的那样,当位以二进制补码解释时,它将-128更改为32。

因此,如果要移位以除以2的幂,则需要算术右移(v >> n)。它返回一个值,其中in中的位v已向右移了n位位置,并且v的最左位的副本从左侧移入:

01111111 >> 2 = 00011111
10000000 >> 2 = 11100000

当这些位是二进制补码表示形式的数字时,算术右移具有除以2的幂的作用。这是有效的,因为最左边的位是符号位。除以2的幂必须保持符号相同。


38

>>>总是将0放在最左边,而>>根据其符号是1还是0。


10

阅读更多有关按位和移位运算符的信息

>>      Signed right shift
>>>     Unsigned right shift

位模式由左操作数给出,移位的位置数由右操作数给出。无符号的右移运算符移位到最左位置>>>

而最左边的位置在 >>取决于符号扩展名。

简单来说,>>>总是移到最左侧,>>根据数字的符号进行移位,即1表示负数,0表示正数。


例如,尝试使用负数和正数。

int c = -153;
System.out.printf("%32s%n",Integer.toBinaryString(c >>= 2));
System.out.printf("%32s%n",Integer.toBinaryString(c <<= 2));
System.out.printf("%32s%n",Integer.toBinaryString(c >>>= 2));
System.out.println(Integer.toBinaryString(c <<= 2));

System.out.println();

c = 153;
System.out.printf("%32s%n",Integer.toBinaryString(c >>= 2));
System.out.printf("%32s%n",Integer.toBinaryString(c <<= 2));
System.out.printf("%32s%n",Integer.toBinaryString(c >>>= 2));
System.out.printf("%32s%n",Integer.toBinaryString(c <<= 2));

输出:

11111111111111111111111111011001
11111111111111111111111101100100
  111111111111111111111111011001
11111111111111111111111101100100

                          100110
                        10011000
                          100110
                        10011000

谢谢。只需添加注释以引用Integer.MAX_VALUE,Integer.MIN_VALUE,-1、0、1的位表示形式。例如:System.out.println(Integer.MAX_VALUE + ": " + String.format("%32s", Integer.toBinaryString(Integer.MAX_VALUE)).replace(' ', '0')); Integer.MAX_VALUE01111111111111111111111111111111; Integer.MIN_VALUE10000000000000000000000000000000; -111111111111111111111111111111111; 000000000000000000000000000000000; 100000000000000000000000000000001
Andy Dong

6

右移逻辑运算符(>>> N)将比特向右移动N个位置,丢弃符号位,并用0填充N个最左边的位。例如:

-1 (in 32-bit): 11111111111111111111111111111111

之后的>>> 1操作变为:

2147483647: 01111111111111111111111111111111

右移算术运算符(>> N)还将位向右移N个位置,但保留符号位并将N个最左边的位填充1。例如:

-2 (in 32-bit): 11111111111111111111111111111110

之后的>> 1操作变为:

-1: 11111111111111111111111111111111
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.