这是天真算法,可计算整数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的某些部分。
在纯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倍或更多。
答案 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);
虽然我不知道为什么。