繁体   English   中英

>>> 和 >> 之间的区别

[英]Difference between >>> and >>

Java中的>>>>>运算符有什么区别?

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

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

例如:-2 用 8 位表示将是11111110 (因为最高有效位具有负权重)。 使用算术移位将其右移一位将为您提供11111111或-1。 然而,逻辑右移并不关心该值是否可能表示一个有符号数。 它只是将所有内容向右移动并从左侧填充 0。 使用逻辑移位将我们的 -2 右移一位将得到01111111

>>>是无符号移位; 它将插入 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。

相关问题

>>>将始终在最左边放置一个 0,而>>将放置一个 1 或 0,具体取决于它的符号是什么。

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

文档中:

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

逻辑右移 ( v >>> n ) 返回一个值,其中v中的位已右移n位,0 从左侧移入。 考虑移位 8 位值,用二进制编写:

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

如果我们将这些位解释为无符号非负整数,则逻辑右移具有将数字除以相应 2 的幂的效果。但是,如果数字采用二进制补码表示,则逻辑右移不会正确除以负数. 例如,当这些位被解释为无符号数时,上面的第二次右移将 128 移位到 32。 但它会从 -128 转移到 32,这在 Java 中很典型,这些位被解释为二进制补码。

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

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

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

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

>>      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

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

-1 (in 32-bit): 11111111111111111111111111111111

>>> 1操作后变为:

2147483647: 01111111111111111111111111111111

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

-2 (in 32-bit): 11111111111111111111111111111110

>> 1操作后变为:

-1: 11111111111111111111111111111111
 Signed right shift
 Unsigned right shift

例子:-

byte x, y;  x=10;  y=-10;  
SOP("Bitwise Left Shift: x<<2 = "+(x<<2));  
SOP("Bitwise Right Shift: x>>2 = "+(x>>2));  
SOP("Bitwise Zero Fill Right Shift: x>>>2 = "+(x>>>2));  
SOP("Bitwise Zero Fill Right Shift: y>>>2 = "+(y>>>2));

output 将是:-

Bitwise Left Shift: x<<2 = 40
Bitwise Right Shift: x>>2 = 2
Bitwise Zero Fill Right Shift: x>>>2 = 2
Bitwise Zero Fill Right Shift: y>>>2 = 1073741821

>>(signed)会给你不同的结果 8 >> 2, -8 >> 2。

右移 8

8 = 1000(二进制)

执行 2 位右移

8 >> 2:

1000 >> 2 = 0010(相当于 2)

-8 右移

8 = 1000(二进制)

1 的补码 = 0111

2的补码:

0111 + 1 = 1000

有符号位 = 1

执行 2 位右移(在 2 的共同结果上)

8 >> 2:

1000 >> 2 = 1110(相当于-2)


>>(unsigned)会给你同样的结果 8 >>> 2, -8 >>> 2。

无符号右移 8

8 = 1000

8 >>> 2 = 0010

-8 的无符号右移

-8 = 1000

-8 >>> 2 = 0010

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM