你真的瞭解JavaScript的右移操做嗎?

問題

最近踩了個坑。。。首先,來看個例子吧。html

console.log(4000000000 >> 1);複製代碼

將上面代碼在瀏覽器中運行,你會獲得什麼結果呢?瀏覽器

知識介紹

按位操做符

將操做數看成32位的比特序列(由0和1組成),操做操做數的二進制形式,返回值依然是標準的JavaScript數值。ide

按位移動操做符

先將操做數轉換爲大端字節序的32位整數,並返回與左操做數相同類型的結果。htm

字節序

計算機是以字節爲單位進行存儲的,一個字節是8位bit,用32位bit表示的整數會佔4個字節,這4個字節的在計算機中存儲的相對位置關係就構成了字節序。blog

簡單來講,大端字節序就是32位整數中,高位字節在前,和咱們平時的閱讀順序是一致的。ip

實踐

上面的知識有點抽象,看過以後應該手動黑人問號❓get

爲了簡單起見,咱們用2^31(16進製表示爲8FFF)這個數來進行問題出現的緣由。it

var num = Math.pow(2, 31);console.log(num >> 1);複製代碼

原理分析

num的32位bit表示爲:1000,0000,0000,0000console

右移一位後數值的二進制表示爲:1100,0000,0000,0000class

按照有符號數在計算機內的表示形式(二進制補碼),具體內容能夠參考這篇文章。咱們能夠將移位後的二進制補碼轉換成原碼:

  1. 對非符號位進行取反,結果爲:1000,1111,1111,1111
  2. 對取反結果加1,結果爲:1100,0000,0000,0000
  3. 因爲最高位是符號爲,咱們獲得結果爲-Math.pow(2, 30) = -1073741824

換一種思路

32位補碼1000,0000,0000,0000,表示的有符號數是:-Math.pow(2,31) = -2147483648, 這個數右移一位(除以2)後,就是-1073741824

超過32bit的數怎麼辦

粗暴截取低32位,而後按照上述方式進行移動,能夠試試下面的代碼,應該能進一步理解。

console.log(Math.pow(2,32) >> 1);console.log((Math.pow(2,32) + Math.pow(2,31)) >> 1);複製代碼

總結

因爲JavaScript自己能表示的整數是比較大的(能夠經過Number.MAX_SAFE_INTEGER進行查看),因此反倒顯得其右移操做比較奇怪。

在不能肯定數值的大小範圍時,仍是老老實實使用除法操做會比較好

相關文章
相關標籤/搜索