猿问

如何用JavaScript通过位序列做标志位(大于32位)

1.我需要通过JavaScript来用位序列做标志位,来表示相对应的数据块存在或不存在,需要能够存取特定位,能够实现类似shift的移位功能,我知道在32位以内很容易实现,但是我需要实现更大的,比如说1024位(利用arraybuffer),这样在存取特定位上没有问题,但是在移位上却是有问题的,不知道有没有办法能够实现,如果有具体如何,希望能有一些指点,谢谢?(补充一点:移位的时候需要后面的位相应补位,也就是说,我的标志位是对应的一个序列,类似一一个队列的样子,只是里面的元素是通过位来标志值是否存在)

湖上湖
浏览 506回答 1
1回答

一只萌萌小番薯

之前说 JavaScript 最大支持 31 位的整数,抱歉,说错了,我用&nbsp;Number.MAX_SAFE_INTEGER.toString(2).length计算了一下,结果是&nbsp;53,也就是说 JavaScript 最大支持 53 位的整数。因此,我修改了答案。可以用&nbsp;Uint32Array、Uint16Array&nbsp;或者&nbsp;Uint8Array&nbsp;来封装&nbsp;ArrayBuffer&nbsp;来进行处理。按习惯用&nbsp;Uint32Array&nbsp;或&nbsp;Uint8Array&nbsp;合适一些。理论上&nbsp;Uint32Array&nbsp;会更快,但实际上要看 ArrayBuffer 的具体实现,这里不做速度上的比较。然后一般的位操作都直接算 index 就了,只有位移操作的时候需要计算上个位移移出的部分。Uint8Array&nbsp;实现先写的这个答案,留在这了。后面用&nbsp;Uint32Array&nbsp;的实现可能更好一些。下面写了一个左移一位的操作,为了简化测试,只字义了4个字节(按字节而不是按整数处理的,所以可以模拟多个单元的情况)var&nbsp;buffer&nbsp;=&nbsp;new&nbsp;ArrayBuffer(4);var&nbsp;iBuffer&nbsp;=&nbsp;new&nbsp;Uint8Array(buffer); iBuffer[0]&nbsp;=&nbsp;0x03; iBuffer[1]&nbsp;=&nbsp;0xf0;console.log(Array.from(iBuffer).map(n&nbsp;=>&nbsp;n.toString(2)));//&nbsp;[&nbsp;'11',&nbsp;'11110000',&nbsp;'0',&nbsp;'0'&nbsp;]let&nbsp;rest&nbsp;=&nbsp;0;for &nbsp;(let&nbsp;i&nbsp;=&nbsp;iBuffer.length&nbsp;-&nbsp;1;&nbsp;i&nbsp;>=&nbsp;0;&nbsp;i--)&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;const&nbsp;v&nbsp;=&nbsp;iBuffer[i];&nbsp;&nbsp;&nbsp;&nbsp;const&nbsp;newRest&nbsp;=&nbsp;(v&nbsp;&&nbsp;0x80)&nbsp;>&nbsp;0&nbsp;?&nbsp;1&nbsp;:&nbsp;0; &nbsp;&nbsp;&nbsp;&nbsp;iBuffer[i]&nbsp;=&nbsp;((v&nbsp;<<&nbsp;1)&nbsp;|&nbsp;rest)&nbsp;&&nbsp;0xff; &nbsp;&nbsp;&nbsp;&nbsp;rest&nbsp;=&nbsp;newRest; }console.log(Array.from(iBuffer).map(n&nbsp;=>&nbsp;n.toString(2)));//&nbsp;[&nbsp;'111',&nbsp;'11100000',&nbsp;'0',&nbsp;'0'&nbsp;]如果需要移多位,对&nbsp;Uint8Array&nbsp;来说,8位以内,都可以通过位移来算&nbsp;newRest,比如,移3位的情况const&nbsp;newRest&nbsp;=&nbsp;v&nbsp;>>&nbsp;(8&nbsp;-&nbsp;3);但是对于移位大于 8 的情况就比较复杂一些了,需要计算 index 偏移(或者 8 位 8 位的移,再处理余下不足 8 位的情况)。所以总的来说我觉得这个算法还是比较考人的,不过我没搜到合适的 BitInteger 库,只找到一个&nbsp;没提供位运算的,可以试试通过乘法(×2)和除法(÷2)来实现。又试验了一下,可以用 Uint32Array 来实现这样操作起来可能会更快一些var&nbsp;buffer&nbsp;=&nbsp;new&nbsp;ArrayBuffer(16);var&nbsp;iBuffer&nbsp;=&nbsp;new&nbsp;Uint32Array(buffer); iBuffer[0]&nbsp;=&nbsp;0x03; iBuffer[1]&nbsp;=&nbsp;0x8f000000;console.log(Array.from(iBuffer).map(n&nbsp;=>&nbsp;n.toString(2)));//&nbsp;bits&nbsp;需要小于32function&nbsp;shift(buffer,&nbsp;bits)&nbsp;{&nbsp; &nbsp;&nbsp;&nbsp;let&nbsp;rest&nbsp;=&nbsp;0;&nbsp;&nbsp;&nbsp;&nbsp;for&nbsp;(let&nbsp;i&nbsp;=&nbsp;iBuffer.length&nbsp;-&nbsp;1;&nbsp;i&nbsp;>=&nbsp;0;&nbsp;i--)&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;const&nbsp;v&nbsp;=&nbsp;iBuffer[i];&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;const&nbsp;newRest&nbsp;=&nbsp;v&nbsp;>>>&nbsp;(32&nbsp;-&nbsp;bits); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;iBuffer[i]&nbsp;=&nbsp;((v&nbsp;<<&nbsp;bits)&nbsp;|&nbsp;rest)&nbsp;&&nbsp;0xffffffff; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rest&nbsp;=&nbsp;newRest; &nbsp;&nbsp;&nbsp;&nbsp;} } shift(iBuffer,&nbsp;5);console.log(Array.from(iBuffer).map(n&nbsp;=>&nbsp;n.toString(2)));输出[&nbsp;'11',&nbsp;'10001111000000000000000000000000',&nbsp;'0',&nbsp;'0'&nbsp;] [&nbsp;'1110001',&nbsp;'11100000000000000000000000000000',&nbsp;'0',&nbsp;'0'&nbsp;]
随时随地看视频慕课网APP

相关分类

JavaScript
我要回答