当前位置:  开发笔记 > 编程语言 > 正文

在JavaScript中将整数转换为任意排序的字节数组的最快方法?

如何解决《在JavaScript中将整数转换为任意排序的字节数组的最快方法?》经验,为你挑选了1个好方法。

我希望将JavaScript编号的MIN_SAFE_INTEGER通过MAX_SAFE_INTEGER范围(不包括符号的53位)转换为分布在7个字节的位串,移位2以允许符号和空标识符.

到目前为止,我提出的最好的是:

function toUint8Array(data) {
    data = data.toString(2);
    data = new Array(65 - data.length).join('0') + data;
    var ret = new Uint8Array(data.length / 8);
    for (var i = 0; i < 8; i++) {
        ret[i] = 0;
        ret[i] += (data[i * 8] == '1' ? 128 : 0);
        ret[i] += (data[(i * 8) + 1] == '1' ? 64 : 0);
        ret[i] += (data[(i * 8) + 2] == '1' ? 32 : 0);
        ret[i] += (data[(i * 8) + 3] == '1' ? 16 : 0);
        ret[i] += (data[(i * 8) + 4] == '1' ? 8 : 0);
        ret[i] += (data[(i * 8) + 5] == '1' ? 4 : 0);
        ret[i] += (data[(i * 8) + 6] == '1' ? 2 : 0);
        ret[i] += (data[(i * 8) + 7] == '1' ? 1 : 0);
    }
    return (ret);
}

小提琴

正如您所知道的那样,这将是非常缓慢的(并且所有7个活动字节中的位仍然没有被移位两个位置.)

有没有办法更快地做到这一点?理想情况下,完全避免字符串解析?



1> hexwab..:

javascript中的按位运算只有32位宽.但是,移位相当于乘法或除以2的幂,并且这些以完全浮点精度发生.

所以你想要做的就是直截了当.移位以获得低阶位中的有趣部分,并屏蔽其余部分.例如,你有一个大数字0x123456789abc(20015998343868).

0x123456789abc/0x1 = 0x123456789abc.按位与0xff给出0xbc.

0x123456789abc/0x100 = 0x123456789a.bc.按位与0xff给出0x9a.

0x123456789abc/0x10000 = 0x12345678.9abc.按位与0xff给出0x78.

等等.码:

function toUint8Array(d) {
    var arr = new Uint8Array(7);
    for (var i=0, j=1; i<7; i++, j *= 0x100) {
        arr[i] = (d / j) & 0xff;
    }
    return arr;
}

使用Uint8Array更简单:使用0xff进行屏蔽是隐含的,因为Uint8Arrays只能存储0到255之间的整数.但为了清晰起见,我将其保留,因此结果将与不同的数组类型相同.

此代码生成一个little-endian数组,例如 toUint8Array(0x123456789abc)return [0xbc,0x9a,0x78,0x56,0x34,0x12,0].如果你想要big-endian,即相反顺序的字节,请替换arr[i]arr[6-i].

(如果你希望每个数组条目中的以相反的顺序,这稍微复杂一些.替换(d / j) & 0xffbitrev((d / j) & 0xff),其中bitrev看起来像这样:

function bitrev(byte) {
   var table = [ 0b0000, 0b1000, 0b0100, 0b1100, 0b0010, 0b1010, 0b0110, 0b1110,
                 0b0001, 0b1001, 0b0101, 0b1101, 0b0011, 0b1011, 0b0111, 0b1111 ];
   return table[byte >> 4] + (table[byte & 0xf] << 4);
}

)

最后,这只适用于正整数.但是你的两个想法很容易实现. d*4被左移两位.而d < 0 ? -d : d(或Math.abs(d))是绝对值d.因此arr = toUint8Array((d<0) ? 1-d*4 : d*4)返回d向左移位两位,符号位在最低有效位(LSB)中.

并且您可以检查非数字isFinite(),但是您必须小心地仅在数字上调用它,因为isFinite(null),实际上是true由于隐式转换规则(这在ES6中已修复):

function toUint8Array_shifted_signed(d) {
   /* bit 0 is sign bit (0 for +ve); bit 1 is "not-a-number" */
   if (typeof d !== 'number' || !isFinite(d)) {
       d = 2; 
   } else {
       d = (d<0) ? 1-d*4 : d*4;
   }

   return toUint8Array(d);
}

推荐阅读
mobiledu2402851377
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有