簡體   English   中英

通過移位了解正確的移位運算符

[英]Understanding the right shift operator with bit shifting

我很難理解正確的移位運算符。 我了解左移,說我們沒有

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為例。

整數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 刪除

111110101當右移3時得到111110 ,刪除加粗的位111110 101

有幾種方法可以查看它。

首先,整數數值類型(在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 ++中的情況更為復雜。 例如, 左移負數是未定義的

假設我們有一個數字(我們將其簡單化,例如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 ,您將看到預期的結果。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM