繁体   English   中英

在 JavaScript 中平方一个数字的最快方法是什么?

[英]What's the fastest way to square a number in JavaScript?

在 JavaScript 中平方一个数字的最快方法是什么?

function squareIt(number) {
   return Math.pow(number,2);
}

function squareIt(number) {
   return number * number;
}

或者其他一些我不知道的方法。 我不是在寻找一个完美的答案,而是平均而言在编译器中可能最短的答案。

编辑:我看到了为什么对一个数字进行平方比将两个随机数相乘要快? 这似乎表明平方比将两个随机数相乘要快,并假设 n*n 不会利用这一点,但 Math.pow(n,2) 会。 正如 jfriend00 在评论中指出的那样,然后在回答中指出, http: //jsperf.com/math-pow-vs-simple-multiplication/10 似乎表明直接乘法在除 Firefox 之外的所有东西中都更快(两种方式同样快)。

注意:随着浏览器引擎改变其优化工作方式,此类问题会随着时间而改变。 对于最近的比较:

Math.pow(x1, 2)
x1 * x1
x1 ** 2                  // ES6 syntax

查看此修订后的性能测试并在您关心的浏览器中运行它: https : //jsperf.com/math-pow-vs-simple-multiplication/32

截至 2020 年 4 月,Chrome、Edge 和 Firefox 在上述所有三种方法之间的差异均不到 1%。

如果 jsperf 链接不起作用(似乎偶尔会宕机),那么您可以尝试这个perf.link 测试用例

2014 年的原始答案:

所有性能问题都应该通过测量来回答,因为浏览器实现的细节和您关心的特定场景通常决定了结果(因此理论讨论并不总是正确的)。

在这种情况下,浏览器实现的性能差异很大。 以下是此 jsperf 测试中许多不同浏览器的结果: http ://jsperf.com/math-pow-vs-simple-multiplication/10 比较:

Math.pow(x1, 2)
x1 * x1

更长的条形更快(更大的操作数/秒)。 您可以看到 Firefox 优化了这两种操作,使其几乎相同。 在其他浏览器中,乘法要快得多。 IE 是最慢的,并且显示出两种方法之间的最大百分比差异。 Firefox 是最快的,两者之间的差异最小。

在此处输入图片说明

ES6 中,您可以使用指数n ( x ** y ) 执行以下操作,这会产生与Math.pow(x,y)相同的结果:

 function squareIt(number) { return number ** 2; } console.log(squareIt(5));

或者你可以使用一个名为BigInteger.js的 JavaScript 库来达到这个目的。

 alert(bigInt(5).square());
 <script src="https://cdnjs.cloudflare.com/ajax/libs/big-integer/1.6.40/BigInteger.min.js"></script>

通常, x * x 比任何语言中的 pow() 调用快得多或大致相同。 pow() 是一个设计用于处理浮点参数的通用指数,它通常使用比单个乘法具有更多运算的计算。 这是出了名的慢。 一些 pow() 实现将有助于过滤掉特殊计算的整数幂,例如对于 x^4,它可能会执行 x2=x * x, x4=x2 * x2,但是添加这样的特殊条件会减慢一般实现的速度,并且x * x vs. pow() 规则在程序员中是众所周知的,你不能真正指望库实现来帮助你。 这是数值分析中的标准建议:永远不要对 x^2(或 x^.5)使用 pow()。 充其量,它并不比 pow 实现慢,如果它在编译时优化为 x * x ,最糟糕的是,它会慢得多(而且可能也不那么准确)。 您可以在您希望代码运行的每个可能的平台上对其进行测试,但在现实生活中,没有充分的理由将 pow() 用于正方形。 编写一个执行 x * x 的便利函数可能有很好的理由,但如果语言允许,最好确保它被标记,以便在机器级别没有实际的函数调用。 不幸的是,我不认为 Javascript 有这样的东西,但我怀疑 JIT 编译器通常足够聪明,可以在不跳转的情况下呈现这样的短函数。

关于 x * x 与 x * y 的问题,前者通常会更快,因为它避免了机器级别的 MOV(除了您引用的帖子中的考虑因素),但可以肯定的是 JS 引擎是如果操作数已经在寄存器中,则足够聪明,不会执行额外的 MOV。 它不会从内存加载 x 然后再次从内存加载它,或者将它从一个寄存器移到另一个寄存器。 这是优化编译器的基本行为。 你必须记住,编译器会对代数运算进行大量的重新排列和合并,所以当你写 x * x 时,很多事情可能会发生,这取决于 x 之前发生了什么或发生在它身上之后。 这是避免 pow() 的另一个原因,因为优化器可以对 x * x 执行很多技巧,如果它改为执行 pow() 调用,则这些技巧可能不可用。 同样,您可以希望它智能地将 pow(x,2) 内联到 x * x,但不要指望它。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM