javascript中最快的斜边?

时间:2012-04-13 12:14:04

标签: javascript math approximation

我在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不可用。

5 个答案:

答案 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

enter image description here

答案 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)

您可以看到xy的平等。如果等于,则可以将斜边计算为(x + y)/sqrt(2),其中sqrt(2)是常量。

因此,此方法可用于x = y的情况。对于其他情况,它可以使用最大不精确度~41%。这是一个很大的错误。但是,当您指定允许的错误限制时,可以使用此方法。例如,如果将允许的错误定义为5%,则b必须介于0.515*a1.942*a之间。

因此,如果您不需要完美的计算不精确,则可以使用数值范围提高计算性能。

通过类比,您可以看到xyzero的平等。并且通过一定的准确度,可以更快地计算斜边的情况。

P.S。我在一个russian article中读到了这个。