18

我在 javascript 中看到了许多关于模拟和动画的问题,这些问题通常涉及计算斜边:

hypot = Math.sqrt(x*x + y*y);

由于笛卡尔坐标是大多数这些引擎的首选武器,因此需要这些计算来找到点对之间的距离等。因此,计算斜边的任何加速都可能对许多项目有很大帮助。

为此,你能看到比上面的简单实现更快的方法吗?基于SuperCollider 中的近似函数,我发现了一个近似值,它在 Chrome 中稍微快一点,但在 Firefox 中却慢得多。

编辑 2015-08-15:我已将接受的答案切换为 Math.hypot 之一;我怀疑目前的务实方法是使用 Math.hypot 或合成的 hypot 函数(如果不可用),如果足够且 Math.hypot 不可用,则与平方(根据 sch 的答案)进行比较。

4

5 回答 5

20

通常,您不需要计算平方根hypot^2 = x*x + y*y就足够了。例如,如果您想比较距离并且不需要实际值,就是这种情况。

于 2012-04-13T12:18:22.707 回答
11

在 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");

Note: 在这个测试中,它使用了 ES6 的Math.hypot

在此处输入图像描述

于 2015-06-24T19:22:02.743 回答
9

许多人不知道的重要一点:

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/

于 2014-09-02T17:55:03.903 回答
2

性能取决于 javascript 运行环境Math.sqrt()Math.hypot()

我只是在 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

铬 88.0.4324.150:

26474.060000036843
422.13000007905066

火狐 85.0.2:

423
419

这意味着 V8 对 Math.hypot() 的实现很糟糕。实际上,如果它也取决于 CPU 架构/型号,我不会感到惊讶。

请注意,在我的示例中,我将整数提供给Math.sqrt()Math.hypot()。另一项测试显示,对于浮点数,Node.js 运行测试代码比在整数上慢 20%。在 ChromeMath.sqrt()中,性能完全相同,Math.hypot()运行速度要慢 3%。火狐:没有区别。

于 2021-02-15T22:49:42.297 回答
1

您可以查看 和 的相等xy。如果等于,您可以将斜边计算为(x + y)/sqrt(2)常数sqrt(2)

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

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

x以此类推,您可以查看或y的相等性zero。并且对于这种情况,可以更快地计算出斜边。

PS 我在一篇俄罗斯文章中读到了这一点。

于 2012-04-13T12:36:07.847 回答