ECMAScript 位元運算符

來源:互聯網
上載者:User

標籤:style   blog   http   color   使用   strong   

位元運算符是在數字底層(即表示數位 32 個數位)進行操作的。

重溫整數

ECMAScript 整數有兩種類型,即有符號整數(允許用正數和負數)和不帶正負號的整數(只允許用正數)。在 ECMAScript 中,所有整數字面量預設都是有符號整數,這意味著什麼呢?

有符號整數使用 31 位表示整數的數值,用第 32 位表示整數的符號,0 表示正數,1 表示負數。數值範圍從 -2147483648 到 2147483647。

可以以兩種不同的方式儲存二進位形式的有符號整數,一種用於儲存正數,一種用於儲存負數。正數是以真二進位形式儲存的,前 31 位中的每一位都表示 2 的冪,從第 1 位(位 0)開始,表示 20,第 2 位(位 1)表示 21。沒用到的位用 0 填充,即忽略不計。例如,展示的是數 18 的標記法。

18 的二進位版本只用了前 5 位,它們是這個數位有效位。把數字轉換成二進位字串,就能看到有效位:

var iNum = 18;alert(iNum.toString(2));//輸出 "10010"

這段代碼只輸出 "10010",而不是 18 的 32 位表示。其他的數位並不重要,因為僅使用前 5 位即可確定這個十進位數值。如所示:

負數也儲存為二進位代碼,不過採用的形式是二進位補碼。計算數字二進位補碼的步驟有三步:

  1. 確定該數位非負版本的二進位表示(例如,要計算 -18的二進位補碼,首先要確定 18 的二進位表示)
  2. 求得二進位反碼,即要把 0 替換為 1,把 1 替換為 0
  3. 在二進位反碼上加 1

要確定 -18 的二進位表示,首先必須得到 18 的二進位表示,如下所示:

0000 0000 0000 0000 0000 0000 0001 0010

接下來,計算二進位反碼,如下所示:

1111 1111 1111 1111 1111 1111 1110 1101

最後,在二進位反碼上加 1,如下所示:

1111 1111 1111 1111 1111 1111 1110 1101                                      1---------------------------------------1111 1111 1111 1111 1111 1111 1110 1110

因此,-18 的二進位表示即 1111 1111 1111 1111 1111 1111 1110 1110。記住,在處理有符號整數時,開發人員不能訪問 31 位。

有趣的是,把負整數轉換成二進位字串後,ECMAScript 並不以二進位補碼的形式顯示,而是用數字絕對值的標準二進位代碼前面加負號的形式輸出。例如:

var iNum = -18;alert(iNum.toString(2));    //輸出 "-10010"

這段代碼輸出的是 "-10010",而非二進位補碼,這是為避免訪問位 31。為了簡便,ECMAScript 用一種簡單的方式處理整數,使得開發人員不必關心它們的用法。

另一方面,不帶正負號的整數把最後一位作為另一個數位處理。在這種模式中,第 32 位不表示數位符號,而是值 231。由於這個額外的位,不帶正負號的整數的數值範圍為 0 到 4294967295。對於小於 2147483647 的整數來說,不帶正負號的整數看來與有符號整數一樣,而大於 2147483647 的整數則要使用位 31(在有符號整數中,這一位總是 0)。

把不帶正負號的整數轉換成字串後,只返回它們的有效位。

注意:所有整數字面量都預設儲存為有符號整數。只有 ECMAScript 的位元運算符才能建立不帶正負號的整數。

位元運算 NOT

位元運算 NOT 由否定號(~)表示,它是 ECMAScript 中為數不多的與二進位算術有關的運算子之一。

位元運算 NOT 是三步的處理過程:

  1. 把運算數轉換成 32 位元字
  2. 把位元轉換成它的二進位反碼
  3. 把位元轉換成浮點數

例如:

var iNum1 = 25;        //25 等於 00000000000000000000000000011001var iNum2 = ~iNum1;    //轉換為 11111111111111111111111111100110alert(iNum2);        //輸出 "-26"

位元運算 NOT 實質上是對數字求負,然後減 1,因此 25 變 -26。用下面的方法也可以得到同樣的方法:

var iNum1 = 25;var iNum2 = -iNum1 -1;alert(iNum2);    //輸出 -26
位元運算 AND

位元運算 AND 由和號(&)表示,直接對數位二進位形式進行運算。它把每個數字中的數位對齊,然後用下面的規則對同一位置上的兩個數位進行 AND 運算:

第一個數字中的數位
第二個數字中的數位
結果

例如,要對數字 25 和 3 進行 AND 運算,代碼如下所示:

var iResult = 25 & 3;alert(iResult);//輸出 "1"

25 和 3 進行 AND 運算的結果是 1。為什嗎?分析如下:

25 = 0000 0000 0000 0000 0000 0000 0001 1001  3 = 0000 0000 0000 0000 0000 0000 0000 0011---------------------------------------------AND = 0000 0000 0000 0000 0000 0000 0000 0001

可以看出,在 25 和 3 中,只有一個數位(位 0)存放的都是 1,因此,其他數位產生的都是 0,所以結果為 1。

位元運算 OR

位元運算 OR 由符號(|)表示,也是直接對數位二進位形式進行運算。在計算每位時,OR 運算子採用下列規則:

第一個數字中的數位
第二個數字中的數位
結果

仍然使用 AND 運算子所用的例子,對 25 和 3 進行 OR 運算,代碼如下:

var iResult = 25 | 3;alert(iResult);//輸出 "27"

25 和 3 進行 OR 運算的結果是 27:

25 = 0000 0000 0000 0000 0000 0000 0001 1001 3 = 0000 0000 0000 0000 0000 0000 0000 0011--------------------------------------------OR = 0000 0000 0000 0000 0000 0000 0001 1011

可以看出,在兩個數字中,共有 4 個數位存放的是 1,這些數位被傳遞給結果。二進位代碼 11011 等於 27。

位元運算 XOR

位元運算 XOR 由符號(^)表示,當然,也是直接對二進位形式進行運算。XOR 不同於 OR,當只有一個數位存放的是 1 時,它才返回 1。真值表如下:

第一個數字中的數位
第二個數字中的數位
結果

對 25 和 3 進行 XOR 運算,代碼如下:

var iResult = 25 ^ 3;alert(iResult);    //輸出 "26"

25 和 3 進行 XOR 運算的結果是 26:

25 = 0000 0000 0000 0000 0000 0000 0001 1001  3 = 0000 0000 0000 0000 0000 0000 0000 0011---------------------------------------------XOR = 0000 0000 0000 0000 0000 0000 0001 1010

可以看出,在兩個數字中,共有 4 個數位存放的是 1,這些數位被傳遞給結果。二進位代碼 11010 等於 26。

左移運算

左移運算由兩個小於符號表示(<<)。它把數字中的所有數位向左移動指定的數量。例如,把數字 2(等於二進位中的 10)左移 5 位,結果為 64(等於二進位中的 1000000):

var iOld = 2;        //等於二進位 10var iNew = iOld << 5;    //等於二進位 1000000 十進位 64

注意:在左移數位時,數字右邊多出 5 個空位。左移運算用 0 填充這些空位,使結果成為完整的 32 位元字。

注意:左移運算保留數位符號位。例如,如果把 -2 左移 5 位,得到的是 -64,而不是 64。“符號仍然儲存在第 32 位中嗎?”是的,不過這在 ECMAScript 後台進行,開發人員不能直接存取第 32 個數位。即使輸出二進位字串形式的負數,顯示的也是負號形式(例如,-2 將顯示 -10。)

有符號右移運算

有符號右移運算子由兩個大於符號表示(>>)。它把 32 位元字中的所有數位整體右移,同時保留該數的符號(正號或負號)。有符號右移運算子恰好與左移運算相反。例如,把 64 右移 5 位,將變為 2:

var iOld = 64;//等於二進位 1000000var iNew = iOld >> 5;//等於二進位 10 十進位 2

同樣,移動數位後會造成空位。這次,空位位於數位左側,但位於符號位之後。ECMAScript 用符號位的值填充這些空位,建立完整的數字,如所示:

無符號右移運算

無符號右移運算子由三個大於符號(>>>)表示,它將無符號 32 位元的所有數位整體右移。對於正數,無符號右移運算的結果與有符號右移運算一樣。

用有符號右移運算中的例子,把 64 右移 5 位,將變為 2:

var iOld = 64;        //等於二進位 1000000var iNew = iOld >>> 5;    //等於二進位 10 十進位 2

對於負數,情況就不同了。

無符號右移運算用 0 填充所有空位。對於正數,這與有符號右移運算的操作一樣,而負數則被作為正數來處理。

由於無符號右移運算的結果是一個 32 位的正數,所以負數的無符號右移運算得到的總是一個非常大的數字。例如,如果把 -64 右移 5 位,將得到 134217726。如何得到這種結果的呢?

要實現這一點,需要把這個數字轉換成無符號的等價形式(儘管該數字本身還是有符號的),可以通過以下代碼獲得這種形式:

var iUnsigned64 = -64 &gt;&gt;&gt; 0;

然後,用 Number 類型的 toString() 擷取它的真正的位表示,採用的基為 2:

alert(iUnsigned64.toString(2));
這將產生 11111111111111111111111111000000,即有符號整數 -64 的二進位補碼錶示,不過它等於不帶正負號的整數 4294967232。

出於這種原因,使用無符號右移運算子要小心。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.