0

複素数の複素ベキを計算する次のコードがあります。

var ss = a.re*a.re + a.im*a.im;
var arg1 = math.arg(a);
var mag = Math.pow(ss,b.re/2) * Math.exp(-b.im*arg1);
var arg = b.re*arg1 + (b.im * Math.log(ss))/2;
return math.complex(mag*Math.cos(arg), mag*Math.sin(arg));

(複素数は {re: 1, im: 1} のように見え、math.arg は単に Math.atan2(n.im.n.re) を返します。math.complex は複素数のコンストラクタです)

特に複雑というわけではなく、私は効率/精度分析に精通していません。

特に複素数の整数べき乗については、二項展開を使用するとより正確に結果を得ることができるため、より良い結果を得たいと考えています。自分で作成する前に、すでにjavascriptで書かれたようなものを持っている人はいますか? 私は速度についてはあまり心配していませんが、精度についてはもっと心配しています。

4

2 に答える 2

0

つまり、コードは複素数を極形式に変換してから、基本的な指数法則を適用しています。

(a + bi)^ n=[n次多項式展開]のようなものを好むとあなたは主張します

あなたはあなたが正確さについて心配していると言います。

私が考えることができる不正確さの3つの原因があります

  • javascript番号:javascriptを使用している場合、精度を心配するのは危険です。整数は実際には浮動小数点数であり、非常に大きな数を処理する場合、これが原因で整数で精度エラーが発生する可能性があります。注意してください。
  • 数学関数:Math.powとMath.atan2が結果をどれだけ正確に計算するか。必要に応じて、これを調べることができます。
  • 丸め誤差:ドメイン/プリイメージに関連して操作の範囲/イメージを拡大する多数の操作を実行すると、丸め誤差が悪化する可能性があります。

懸念すべき非効率性の原因もあります。多項式展開を使用してz^nを計算するには、O(n)時間とO(n)空間が必要であり、これは絶対にひどいことです。

指数を分解することで、O(log(n))時間とO(1)またはO(log(n))スペース(以前のO(1)時間とスペースとは対照的にまだかなり悪い)をとることができますnをそのバイナリ表現に変換します。

結局、あなたはまだ浮動小数点表現を計算しています。(基本的に)1つの操作を実行できる場合、それを計算するために長い一連の操作を実行する理由はありません。その操作が非常に不正確でない限り、実行する操作が少ないほどエラーが少なくなることを期待する必要があります。

精度にはるかに大きな影響を与えるのは、使用すると予想される数値の分布(非常に小さい、非常に大きい、両方など)と表現の選択(たとえば、極座標またはデカルト形式で自然に表現することを選択した場合)です。 )。たとえば、多くの加算と減算を行う予定の場合、デカルト座標を使用すると、丸め誤差が少なくなり、速度が向上する可能性があります。多くの乗算、除算、べき乗を実行する場合、または指数スケールで作業する場合は、極座標を使用すると、丸め誤差が少なくなり、速度が向上する可能性があります。

于 2012-04-26T11:14:01.630 に答える
0

整数の累乗のみを気にする場合、最も正確なのは、それらを乗算することです。

var Re = 0, Im = 1;
var newRe = 1, newIm = 0;
var retRe = 1, retIm = 0;
for(var i = 0; i < n; i++)
{
    newRe = retRe * Re - retIm * Im;
    newIm = retRe * Im + retIm * Re;
    retRe = newRe;
    retIm = newIm;
}
于 2012-04-27T08:08:35.230 に答える