【轉載】位運算

重溫整數

https://www.xp.cn/e/js/pro_js_operators_bitwise.html
(現在放著,有空在此基礎上做筆記)

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 位即可確定這個十進制數值。如下圖所示:

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

確定該數字的非負版本的二進制表示(例如,要計算 -18的二進制補碼,首先要確定 18 的二進制表示)

求得二進制反碼,即要把 0 替換為 1,把 1 替換為 0

在二進制反碼上加 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
`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 是三步的處理過程:

把運算數轉換成 32 位數字

把二進制數轉換成它的二進制反碼

把二進制數轉換成浮點數

例如:

var iNum1 = 25;``//25 等于 00000000000000000000000000011001`

var iNum2 = ~iNum1;``//轉換為 11111111111111111111111111100110`

alert(iNum2);//輸出 "-26"`

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

var iNum1 = 25;`

var iNum2 = -iNum1 -1;`

alert(iNum2);``//輸出 -26`

位運算 AND

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

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

1 1 1

1 0 0

0 1 0

0 0 0

例如,要對數字 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 運算符采用下列規則:

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

1 1 1

1 0 1

0 1 1

0 0 0

仍然使用 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。真值表如下:

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

1 1 0

1 0 1

0 1 1

0 0 0

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

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

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

25 = 0000 0000 0000 0000 0000 0000 0001 10013 = 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 >>> 0;

然后,用 Number 類型的 toString() 獲取它的真正的位表示,采用的基為 2:

alert(iUnsigned64.toString(2));

這將生成 11111111111111111111111111000000,即有符號整數 -64 的二進制補碼表示,不過它等于無符號整數 4294967232。

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

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,663評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,125評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,506評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,614評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,402評論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,934評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,021評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,168評論 0 287
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,690評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,596評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,784評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,288評論 5 357
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,027評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,404評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,662評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,398評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,743評論 2 370

推薦閱讀更多精彩內容