js 【 巨难问题 】如何用二进制位操作 替代for 循环减去每一项的算法?

var arr = [12,45,45,323,542,34 .....] 长度是10万上

每一项减去 7 得到一个新数组

用for 还是太慢, 而且是不是占用内存也大?不能用多线程

有没有什么二进制或者位操作之类的奇技淫巧 来瞬间处理这个数组

阅读 2.7k
4 个回答
  1. 预先确定目标数组的长度,楼上的代码如果 x = new Array(150000);的话,时间可能会减小到 5ms 以下;
  2. 采用循环展开,一次读取多个数据,类似于这样写:

    const MAX = 150000;
    const gen = () => (0|(Math.random()*100)),
        a = new Array(MAX);
    let max = MAX;
    while(max--){
        a[max] = gen();
    }
    
    // 上面只是准备,以下才是迭代运算
    const res = new Array(MAX);
    // 每个周期读出多个数,有效减少时间复杂度
    for(let cnt = 0; cnt < MAX; cnt += 10){
        res[cnt] = a[cnt] - 7;
        res[cnt + 1] = a[cnt + 1] - 7;
        res[cnt + 2] = a[cnt + 2] - 7;
        // ···以此类推
        res[cnt + 9] = a[cnt + 9] - 7;
    }
  3. 查表,也就是缓存计算结果,这样可以减少运算,应用范围仅限于 被减数取值范围远小于数组长度 的情形,适用于长期运行的项目;
  4. 使用 asmjs,类型标注可以加快执行,配合二进制预先求出 7 的补码将减法转为加法运算来加速,不过由于现代浏览器会采用类似分支预测的方式执行迭代,JS 进行纯数值的大规模迭代运算不会比 asm 慢太多;
  5. 使用 WASM,比asm快,不过由于通信开销大(每个数据复制一遍,除非浏览器已经引入/恢复 SharedArrayBuffer),可能毫无优势,除非数据绝大部分生命周期都在 WASM里面。

手写 150000 行代码,就可以有效避免使用循环,我太机智了

单纯的for循环,15万,约10毫秒,这速度还可以接受啊!稍微优化下,还能快一丢丢。
image.png

image.png

突然想起之前看到的达夫设备可以优化循环,你可以试试

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏