通过位移理解右移位算子

问题描述 投票:1回答:5

我很难理解右移操作员。我理解左移。我们没有

int n = 11; which is 1011

现在,如果我们离开它n << 1结果是

int a = n << 1 ; so a = 10110; (simply add a 0 to the end)

这是有道理的

现在正确的转变是我遇到困难的地方

int a = n >> 1

我认为答案是01011(在前面添加0),这将是1011而不是101.我的问题是我们是如何松开最后一位数的。

更新:我的推理可能是假设int是8位,在这种情况下我们将int8 n = 1011 =>这是00001011所以当我们右移1时它超过8位int 1,所以最后一位被删除它变成了0000101?这种理解是否正确?

c++ bit-shift
5个回答
7
投票

好像你对轮班工作有误解。

移位不会向左或向右添加零。你不能只添加数字,只有这么多位。让我们把你的号码,十进制数字11。

int n = 11;这是1011

这是事实,但只有一半的故事。请参阅数字在CPU中具有固定大小。对于整数,即32位,但为了使它更容易,我们假设8位数。你的11看起来像这样:

+-+-+-+-+-+-+-+-+
|0|0|0|0|1|0|1|1|
+-+-+-+-+-+-+-+-+

它有8位。总是。现在让我们左移1:

 +-+-+-+-+-+-+-+-+
0|0|0|0|1|0|1|1| |
 +-+-+-+-+-+-+-+-+

转移后,第一位被“移出”。这个位没有空间存放。另外,最后一位是“空”,我们不能存储“空虚”。只有一个或零。相反,我们“转向”零。所以你最终得到了

+-+-+-+-+-+-+-+-+
|0|0|0|1|0|1|1|0|
+-+-+-+-+-+-+-+-+

在右移,相反。我们再次从11开始:

+-+-+-+-+-+-+-+-+
|0|0|0|0|1|0|1|1|
+-+-+-+-+-+-+-+-+

并向右移1:

+-+-+-+-+-+-+-+-+
| |0|0|0|0|1|0|1|1
+-+-+-+-+-+-+-+-+

同样,每一位都向右移动1.在左边有一个空位,如前所述,只是变为零。在右边,一个被移出,没有空间存储它。它刚刚丢失了。我们的最终号码是:

+-+-+-+-+-+-+-+-+
|0|0|0|0|0|1|0|1|
+-+-+-+-+-+-+-+-+

以上是无符号数,也称为逻辑右移。在二进制补码系统中,对于有符号数,它使用所谓的算术右移,而不是在零位中移位,它在符号位中移位。即如果数字是负数,那么最重要的位是1,它会转换为1,否则它会转为零。


3
投票

右转后,1011将成为101。最正确的一点从1011删除。

当右移3时,111110101给出了111110,去掉了粗体位111110101


3
投票

有几种方法可以看待它。

首先,整数数字类型(在C,C ++,Java,C#中)具有固定的位数。所以实际上是11(假设可读性为罕见的8位int):

 00001101 (8 digits)

左转一点

000011010 (9 digits?)

但由于我们的整数只能管理8位,因此最左边的位会下降。

00011010 (8 digits)

32位整数也是如此:最左边的位下降。

右移也是如此:右边的位下降。如果原件是:

00011010 (8 digits)

然后在左侧添加一个位会产生一个9位值,这是不受支持的。相反,添加的零将所有位推到一个位置,最右边的位下降,结果是

00001101 (8 digits)

另一种看待它的方法就是乘法和除法。在小数中,当我们乘以10时,在右边添加一个零。左移就像乘法,但对于二进制。当我们除以10时,我们删除最右边的数字并将其放在一小部分中。正二元和右移是相同的,我们只是失去了分数。

请注意,对于负数,C ++中的事情会更复杂。例如,left shifting a negative is undefined


1
投票

假设我们有一个数字(我们会很简单,比如00010000),我们想把它向左移位,它看起来像这样:

00010000 << 1 = 00100000

我们取了一个数字,并将列1空间中每列的值放到左边(因为1是我们放在位移的另一个操作数上的数字)。

和我一起到目前为止?好。

现在,正确的转变是做什么的?好吧,它正好相反它将列x空间中每列的值放在右边。例如:

00010000 >> 1 = 00001000

一些更高级的例子:

01010101 << 1 = 10101010
01010101 >> 1 = 00101010

11111111 << 2 = 11111100
11111111 >> 2 = 00111111

注意:位移将切断在数据边界上移位的任何位,例如11111111的示例,在移位丢失后落在边缘上的任何位。


1
投票

你没有“失去”最后一位数。你只是没有改变你认为的价值。

你开始使用n = 0b1011。你将它向左移一位并将结果存储到a中,使n保持不变。然后你将n(仍然有价值0b1011)向右移动并得到了0b0101

如果你把a转移到右边而不是n,你会看到你期望的结果。

© www.soinside.com 2019 - 2024. All rights reserved.