18

javascriptでのシミュレーションとアニメーションに関する多くの質問を見てきました。これには、斜辺の計算が含まれることがよくあります。

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

これらのエンジンのほとんどでデカルト座標が選択される武器であるため、これらの計算は、ポイントのペア間の距離などを見つけるために必要です。したがって、斜辺の計算を高速化すると、多くのプロジェクトに大いに役立ちます。

そのために、上記の単純な実装よりも高速な方法を見ることができますか?私は、Chromeでわずかに速い近似を見つけましたが、SuperColliderのこの近似関数に基づいて、Firefoxでははるかに遅いことがわかりました。

編集2015-08-15:受け入れられた答えをMath.hypotのものに切り替えました。現在の実用的なアプローチは、Math.hypotまたは合成されたhypot関数が利用できない場合はそれを使用し、それで十分でMath.hypotが利用できない場合は、正方形と比較することだと思います。

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

のパフォーマンス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

Firefox 85.0.2:

423
419

これは、V8にMath.hypot()のひどい実装があることを意味します。実際、CPUのアーキテクチャ/モデルにも依存していても、それほど驚かないでしょう。

Math.sqrt()私の例では、とに整数をフィードしていることに注意してくださいMath.hypot()。別のテストでは、浮動小数点数を使用すると、Node.jsが整数よりも20%遅いテストコードを実行することが明らかになりました。ChromeMath.sqrt()のパフォーマンスはまったく同じで、Math.hypot()実行速度は3%遅くなります。Firefox:違いはありません。

于 2021-02-15T22:49:42.297 に答える
1

xとの平等に目を向けることができますy。が等しい場合、は定数(x + y)/sqrt(2)であるため、斜辺を計算できます。sqrt(2)

したがって、この方法はx=yの場合に使用できます。その他の場合は、最大41%の不正確さで使用できます。これは大きなエラーです。ただし、許容誤差限界を指定する場合は、この方法を使用できます。たとえば、許容誤差を5%に定義するbと、との間でなければならないこと0.515*aがわかります1.942*a

したがって、計算の完全な不正確さを必要としない場合は、値の範囲を使用して計算のパフォーマンスを向上させることができます。

類推によって、あなたはまたはの平等に目を向けることができxます。そして、ある程度の精度で、この場合の斜辺をより速く計算します。yzero

PS私は1つのロシアの記事でこれについて読みました。

于 2012-04-13T12:36:07.847 に答える