JavaScript中最快的2次幂?

时间:2014-11-17 03:43:48

标签: javascript double bit-manipulation ieee-754

以下表达式是否有更快的替代方法:

Math.pow(2,Math.floor(Math.log(x)/Math.log(2)))

即,取最接近(较小)的2的整数倍?我在内循环中有这样的表达。我怀疑它可能会快得多,考虑到可以从双尾的IEEE 754表示中获取尾数。

3 个答案:

答案 0 :(得分:8)

利用ES6' Math.clz32(n)来计算32位整数的前导零:



// Compute nearest lower power of 2 for n in [1, 2**31-1]:
function nearestPowerOf2(n) {
  return 1 << 31 - Math.clz32(n);
}

// Examples:
console.log(nearestPowerOf2(9));  // 8
console.log(nearestPowerOf2(33)); // 32
&#13;
&#13;
&#13;

答案 1 :(得分:2)

不幸的是,您需要等效的C函数frexp。我能找到的最好的是JSFiddle,其代码使用Math.pow

您可以使用真实数据以及当前的尝试进行基准测试:

  1. 从1.0开始,重复乘以2.0直到它大于或等于输入,然后乘以0.5直到它小于或等于输入。您需要对双范围末端的值进行特殊处理。
  2. 在双倍范围内存储2的所有精确幂的升序值数组,并进行二分查找。
  3. 如果您的数据通常接近1.0,则第一个可能是最快的。第二个需要最多11个条件分支。

答案 2 :(得分:2)

这是另一种替代方案,带有基准。虽然两者似乎都具有可比性,但我喜欢能够在地板或天花板上使用。

&#13;
&#13;
function pow2floor(v){
    v++;
    var p = 1;
    while (v >>= 1) {p <<= 1;}
    return p;
}
function pow2ceil(v){
    v--;
    var p = 2;
    while (v >>= 1) {p <<= 1;}
    return p;
}

function MATHpow2(v){
    return Math.pow(2,Math.floor(Math.log(v)/Math.log(2)))
}

function runner(fn, val){
    for(var i=0; i<10000000; i++){
       fn(val);
    }
}

var then;
var source = 123456789;

then = new Date().getTime();
runner(pow2floor, source);
console.log(" pow2floor: " + (new Date().getTime() - then ) );

then = new Date().getTime();
runner(MATHpow2, source);
console.log(" MATHpow2: " + (new Date().getTime() - then ) );
&#13;
Attempting to post the results into the HTML here is altering the results. Look in your browsers console fore results.
&#13;
&#13;
&#13;