针对BigInt优化的整数对数base2

时间:2019-03-26 10:43:22

标签: javascript logarithm

这是天真算法,可计算整数log2(n),

  function ilog2(n) {  // n is a positive non-zero BigInt
     const C1 = BigInt(1)
     const C2 = BigInt(2)
     for(var count=0; n>C1; count++)  n = n/C2
     return count
  } // example ilog2(16n)==4

我正在测试优化(请参见下面的示例),但是它们不是commented here的“用于log2”。

使用WebAssembly有更好的选择吗?

PS:如果不可能有通用的解决方案,则可以使用ilog2_64bits(n)之类的函数来使WebAssembly截断或忽略输入BigInt的某些部分。


非WebAssembly

在纯Javascript中没有如此优化的示例(理想情况是WebAssembly!)...尝试改编BigInteger.js的integerLogarithm():

  function ilog2_pe(value, base=2n) {
      // example: ilog2_pe(255n) returns { p: 128n, e: 7n }
      if (base  <= value) {
          let i = ilog2_pe(value, base**2n);
          let t = i.p*base
          return (t <= value)
            ? { p: t,   e: i.e*2n + 1n }
            : { p: i.p, e: i.e*2n }
      }
      return { p: 1n, e: 0n };
  }

  function ilog2_str(n) { // 2*faster!
    return n.toString(2).length - 1
  }

PS:它在现代浏览器和最新版本的NodeJS中运行。


关于性能... {ilog2_pe(x64bits)比单纯的ilog2()快4倍,ilog2_pe(x1024bits)快9倍...可以预期...但是:

任何非WebAssembly解决方案都具有如此出色的性能,即使对于512位,1024位,2048位……使用ilog_str()计数字符串数字也要快2倍! 对于更少的tham,64位快3倍或更多。

1 个答案:

答案 0 :(得分:0)

以下代码在 Firfeox 89、Chrome 90 上似乎比 ilog2_str 快。

function ilog2_str(n) { // 2*faster!
  return n.toString(2).length - 1
}

function ilog2_bs(value) {
  let result = 0n, i, v;
  for (i = 1n; value >> (1n << i); i <<= 1n);
  while (value > 1n) {
    v = 1n << --i;
    if (value >> v) {
      result += v;
      value >>= v;
    }
  }
  return result;
}

testcases = [...Array(10000)].map((n, i) => 13n ** BigInt(i));
testcases.map(ilog2_str);
testcases.map(ilog2_bs);

虽然我不知道为什么。