我很难理解右移操作员。我理解左移。我们没有
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?这种理解是否正确?
好像你对轮班工作有误解。
移位不会向左或向右添加零。你不能只添加数字,只有这么多位。让我们把你的号码,十进制数字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,否则它会转为零。
右转后,1011
将成为101
。最正确的一点从1011
删除。
当右移3时,111110101
给出了111110
,去掉了粗体位111110101
有几种方法可以看待它。
首先,整数数字类型(在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
假设我们有一个数字(我们会很简单,比如00010000
),我们想把它向左移位,它看起来像这样:
00010000 << 1 = 00100000
我们取了一个数字,并将列1
空间中每列的值放到左边(因为1是我们放在位移的另一个操作数上的数字)。
和我一起到目前为止?好。
现在,正确的转变是做什么的?好吧,它正好相反它将列x空间中每列的值放在右边。例如:
00010000 >> 1 = 00001000
一些更高级的例子:
01010101 << 1 = 10101010
01010101 >> 1 = 00101010
11111111 << 2 = 11111100
11111111 >> 2 = 00111111
注意:位移将切断在数据边界上移位的任何位,例如11111111
的示例,在移位丢失后落在边缘上的任何位。
你没有“失去”最后一位数。你只是没有改变你认为的价值。
你开始使用n = 0b1011
。你将它向左移一位并将结果存储到a
中,使n
保持不变。然后你将n
(仍然有价值0b1011
)向右移动并得到了0b0101
。
如果你把a
转移到右边而不是n
,你会看到你期望的结果。