如何加速JavaScript中的Math.pow()函数?

3
我有一些需要每秒执行许多Math.pow()函数调用的代码。测试表明,它是代码性能方面的一个很大瓶颈。
结果不需要非常精确 - 85%以上的准确度就可以了 - 但我的问题是是否有任何方法可以加快这些计算速度?也许以某种精度损失为代价?
编辑:这些计算非常不可能重复,所以缓存无法起作用。

它们之间有什么共同点吗(例如,功率总是整数或总是相同的)? - redbmk
@redbmk 是的,幂次方始终是介于2-5之间的整数。 - user11406
1
请问你能分享一下实现 Math.pow 的相关代码吗?也许我们可以在那里帮助你,很不幸的是,直接猜测更快的解决方案并不容易。如果我们无法在这方面帮助你,你可以尝试使用 codereview,也许一些审核大师可以大大减少你的代码或找到更有效的数学求解方法,谁知道呢! - briosheje
1
@user11406,关于C/C++有一个类似的问题:https://dev59.com/zkzSa4cB1Zd3GeqPkz-H。它对JS有帮助吗? - DWand
1
我更多地来自于C/C++背景以及其他性能关键领域,比如GLSL,但是如果我们知道指数并且它很小,通常我们会避免使用pow。例如,不是使用pow(x, 2),而是使用x*x。在这个本地领域中,这也是相当惯用的做法:float x2 = x*x; float x4 = x2*x2;。我建议将其作为一个KISS策略,而不是使用像pow这样的函数,因为该函数最适合指数未知(在运行时变化)和/或较大的情况。 - user4842163
在某些情况下,如果您有一个固定的指数,您可以大大加快速度。我必须计算 x^1.5,使用 x*Math.sqrt(x)Math.pow(x, 1.5) 快十倍以上。 - Waruyama
2个回答

4

以一定的精度为代价

失去多少精度?如果你只需要正确的答案大致上正确,你可以使用位运算。

function pow2(n) {
  return 2 << (n-1);
}

console.log(pow2(n) === Math.pow(2, n));
< p > Number 构造函数(包括数字字面量)仅使用浮点数。该函数将浮点数转换为 32 位整数,如此描述

否则,我怀疑你将无法击败优化的本地实现 Math.pow


所有我的值都在0-2之间是十进制的。看起来在那些情况下这不会起作用? - user11406
@user11406 很遗憾,不是这样的。 - twinlakes

0

jsPerf 是一个非常好的工具,可以尝试多种技术来找到最快的方法。

这可能会因浏览器或操作系统而有很大差异,但到目前为止,在我的环境中(Chrome 42、64位Linux),Math.pow 要快得多,直到你打开开发者工具。打开开发者工具后,根据幂次数将数字乘以多少次,就像下面的例子一样,速度略微更快:

function pow(num, pow) {
    var result = num;
    while (--pow) {
       result *= num;
    }
    return result;
}

我已经没有更多不同的想法了,但你可以在这里看到我目前为止所拥有的:

http://jsperf.com/math-pow-alternatives

仅仅调用一个函数就需要很多开销(数十万次)。在这种情况下,似乎使用Math.pow是最好的选择,但也可能有其他方法来提高性能(或至少是可感知的性能)。如果代码是阻塞的,并且浏览器出现了一些延迟,您可以尝试使用Web Workers,或者限制每帧计算的数量。您还可以尝试减少函数调用的数量,或确保与DOM的交互非常小(特别是在计算期间,但最好根本不要交互)。

如果没有更简洁的代码示例,将很难微调您的代码性能。


这对像 Math.pow(2, 0.5) 这样的平方根怎么处理? - B''H Bi'ezras -- Boruch Hashem
@bluejayke 这是另一个限制。由于Math.pow使用JavaScript引擎的本地代码,因此通常应该更快,并且比我提供的任何其他示例都更完整,我认为它们都有一个警告,即它们仅适用于正整数。 - redbmk

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接