1 回答

TA貢獻1795條經(jīng)驗 獲得超7個贊
之前說 JavaScript 最大支持 31 位的整數(shù),抱歉,說錯了,我用
Number.MAX_SAFE_INTEGER.toString(2).length
計算了一下,結(jié)果是53
,也就是說 JavaScript 最大支持 53 位的整數(shù)。因此,我修改了答案。
可以用 Uint32Array
、Uint16Array
或者 Uint8Array
來封裝 ArrayBuffer
來進行處理。按習(xí)慣用 Uint32Array
或 Uint8Array
合適一些。理論上 Uint32Array
會更快,但實際上要看 ArrayBuffer 的具體實現(xiàn),這里不做速度上的比較。
然后一般的位操作都直接算 index 就了,只有位移操作的時候需要計算上個位移移出的部分。
Uint8Array
實現(xiàn)
先寫的這個答案,留在這了。后面用
Uint32Array
的實現(xiàn)可能更好一些。
下面寫了一個左移一位的操作,為了簡化測試,只字義了4個字節(jié)(按字節(jié)而不是按整數(shù)處理的,所以可以模擬多個單元的情況)
var buffer = new ArrayBuffer(4);var iBuffer = new Uint8Array(buffer); iBuffer[0] = 0x03; iBuffer[1] = 0xf0;console.log(Array.from(iBuffer).map(n => n.toString(2)));// [ '11', '11110000', '0', '0' ]let rest = 0;for (let i = iBuffer.length - 1; i >= 0; i--) { const v = iBuffer[i]; const newRest = (v & 0x80) > 0 ? 1 : 0; iBuffer[i] = ((v << 1) | rest) & 0xff; rest = newRest; }console.log(Array.from(iBuffer).map(n => n.toString(2)));// [ '111', '11100000', '0', '0' ]
如果需要移多位,對 Uint8Array
來說,8位以內(nèi),都可以通過位移來算 newRest
,比如,移3位的情況
const newRest = v >> (8 - 3);
但是對于移位大于 8 的情況就比較復(fù)雜一些了,需要計算 index 偏移(或者 8 位 8 位的移,再處理余下不足 8 位的情況)。
所以總的來說我覺得這個算法還是比較考人的,不過我沒搜到合適的 BitInteger 庫,只找到一個 沒提供位運算的,可以試試通過乘法(×2)和除法(÷2)來實現(xiàn)。
又試驗了一下,可以用 Uint32Array 來實現(xiàn)這樣操作起來可能會更快一些
var buffer = new ArrayBuffer(16);var iBuffer = new Uint32Array(buffer); iBuffer[0] = 0x03; iBuffer[1] = 0x8f000000;console.log(Array.from(iBuffer).map(n => n.toString(2)));// bits 需要小于32function shift(buffer, bits) { let rest = 0; for (let i = iBuffer.length - 1; i >= 0; i--) { const v = iBuffer[i]; const newRest = v >>> (32 - bits); iBuffer[i] = ((v << bits) | rest) & 0xffffffff; rest = newRest; } } shift(iBuffer, 5);console.log(Array.from(iBuffer).map(n => n.toString(2)));
輸出
[ '11', '10001111000000000000000000000000', '0', '0' ] [ '1110001', '11100000000000000000000000000000', '0', '0' ]
添加回答
舉報