我在javascript中看到了很多关于模拟和动画的问题,这通常涉及计算斜边:
hypot = Math.sqrt(x*x + y*y);
由于笛卡尔坐标是大多数这些引擎中的首选武器,因此需要进行这些计算才能找到各对点之间的距离等。因此,计算斜边的任何加速都可能对许多项目有很大帮助。
为此,您能看到比上述简单实现更快的方法吗?我发现Chrome中的近似值稍微快一些,但基于this approximation function in SuperCollider,Firefox的结果要慢得多。
编辑2015-08-15:我已将接受的答案换成了Math.hypot答案;我怀疑目前的实用方法是使用Math.hypot或合成的hypot函数(如果不可用),并与square(每个sch的答案)进行比较,如果这足够并且Math.hypot不可用。
答案 0 :(得分:14)
通常,您不需要计算平方根,hypot^2 = x*x + y*y
就足够了。例如,如果要比较距离并且不需要实际值,就是这种情况。
答案 1 :(得分:6)
很多人都不知道的重点:
hypot = Math.sqrt(x*x + y*y);
这在理论上有效,但在实践中可能会失败。如果x太大了 x * x溢出,代码将产生无限的结果。
以下是如何计算sqrt(x x + y y)而不会有溢出的风险。
max = maximum(|x|, |y|) min = minimum(|x|, |y|) r = min / max return max*sqrt(1 + r*r)
参考文献和完整文本:John D. Cook - http://www.johndcook.com/blog/2010/06/02/whats-so-hard-about-finding-a-hypotenuse/
答案 2 :(得分:4)
在ECMAScript ES6中,您可以使用 Math.hypot :
// ES5 support
Math.hypot = Math.hypot || function(x, y){ return Math.sqrt(x*x + y*y) }
var x = 3, y = 4;
document.write(Math.hypot(x, y))

编辑:您可以在空白标签上运行此测试,两种方法都有200万次操作,结果非常好,速度提高了24%。
var i, tmp, x = 55, y = 66, end, ini = performance.now();
// Math.sqrt operation
i = 0;
ini = performance.now();
tmp = 0;
while(i++ < 2000000){
tmp += Math.sqrt(x*x + y*y)
}
end = performance.now();
console.log(tmp, "Math.sqrt operation: " + (end - ini) + " ms");
// Math.hypot
i = 0;
ini = performance.now();
tmp = 0;
while(i++ < 2000000){
tmp += Math.hypot(x, y)
}
end = performance.now();
console.log(tmp, "Math.hypot: " + (end - ini) + " ms");
注意:在此测试中,它使用了ES6的 Math.hypot 。
答案 3 :(得分:2)
Math.sqrt()
和 Math.hypot()
的性能取决于 javascript 运行环境。
我只是在 Node.js、Chrome 和 Firefox 中运行此代码:
let z = performance.now();
for (let i = 0; i < 1000000000; i++) {
Math.hypot(i, i);
}
console.log(performance.now() - z);
z = performance.now();
for (let i = 0; i < 1000000000; i++) {
Math.sqrt(i * i + i * i);
}
console.log(performance.now() - z);
结果如下:
Node.js v14.15.4:
24394.656100034714
419.97210001945496
Chrome 88.0.4324.150:
26474.060000036843
422.13000007905066
火狐 85.0.2:
423
419
这意味着 V8 有很糟糕的 Math.hypot() 实现。实际上,如果它也取决于 CPU 架构/型号,我不会感到惊讶。
请注意,在我的示例中,我将整数提供给 Math.sqrt()
和 Math.hypot()
。另一项测试表明,使用浮点数 Node.js 运行测试代码比在整数上慢 20%。在 Chrome 中,Math.sqrt()
的性能完全相同,而 Math.hypot()
的运行速度要慢 3%。火狐:没有区别。
答案 4 :(得分:1)
您可以看到x
和y
的平等。如果等于,则可以将斜边计算为(x + y)/sqrt(2)
,其中sqrt(2)
是常量。
因此,此方法可用于x = y的情况。对于其他情况,它可以使用最大不精确度~41%。这是一个很大的错误。但是,当您指定允许的错误限制时,可以使用此方法。例如,如果将允许的错误定义为5%,则b
必须介于0.515*a
和1.942*a
之间。
因此,如果您不需要完美的计算不精确,则可以使用数值范围提高计算性能。
通过类比,您可以看到x
或y
与zero
的平等。并且通过一定的准确度,可以更快地计算斜边的情况。
P.S。我在一个russian article中读到了这个。