javascript語言特性:Number的bitwise operation(位元操作)是使用32bit處理

最近想要移植C的一些64bit資料處理的小程式到JS上,就遭遇這個問題位元指令32bit的問題。實際上JS所有的位元操作(bitwise operation),諸如:左移(left shift)、右移(right shift)、OR、AND、XOR等都是只能用在32位元內操作。

舉例

1 << 30
得到 1073741824

1 << 31
得到 -2147483648

2147483647 & 0x01
得到 1

2147483648 | 0x01
得到 -2147483647

確認Number規格

查看Number的MDN說明,Number是使用double以IEEE754規格實作的,可以表示的整數範圍應是從-(2^53-1)至2^53- 1,但是為何我放不進去呢? 

AND運算的MDN說明跟一些網站教學有提到,JS的Bitwise都是32bit的

如何解決運算問題?

  1. 使用一般的加減乘除
  2. 使用BigInt

使用一般的加減乘除

例如上面的1 << 31,就改成 1 * 2 ** 31,可以得到 2147483648

使用BigInt

轉成BigInt只需要使用BigInt函數處理即可,不用new運算子。

var value = BigInt(2147483648);

而literal的部份則是多加上n,就可指定使用BigInt,例如

value | 0x01n
得到 2147483649n 

!!注意!! 如果你的運算中間沒有都使用BigInt會產生TypeError的錯誤,訊息如下

Uncaught TypeError: Cannot mix BigInt and other types, use explicit conversions at ....

如何從BigInt轉回Number?

用Number轉型就可以轉回來,例如Number(2147483649n)可得到2147483649,不過如果超過Number可表現的範圍也一樣會錯誤喔

如何判斷BigInt類型?

typeof value === "bigint"

題外話: 你可以測試看看下面這些的結果
2**53-1
2**53
2**53+1
2**53+2
2**53+3
2**53+4

Number(2n**53n-1n)
Number(2n**53n)
Number(2n**53n+1n)
Number(2n**53n+2n)
Number(2n**53n+3n)
Number(2n**53n+4n)


留言