VarComplexCreate にバグ?

解決


ryo-kun  2004-04-07 17:07:39  No: 8263

こんにちは,はじめまして.

Delphi 6から複素数がサポートされているようなので,
使ってみようと思ったのですが,おかしな現象に出会って困っています.
以下のを実行しますと,
var
  dd,tt : variant;
begin
  dd := VarComplexCreate(1E-10, 1E-10);
  dd := 1.0/dd;
  Memo2.Lines.Add(floattostr(dd.Real)+':'+floattostr(dd.Imaginary));
end;
除算のところでゼロ割のエラーが出ます.
おかしいのは,dd := 1.0+1.0iにしたときはこのエラーは出ないのです.

ひょっとしてバグを掘り当ててしまったのでしょうか?
ご存知の方いらっしゃいましたら,よろしくお願いします.
環境は Windows2000 です


にしの  2004-04-07 19:50:24  No: 8264

1E-10の計算途中に、2E-20となり、機械イプシロンの1E-12より小さくなるためゼロと判断されます。
複素数の除算の数式を参考にされると、解決するかと思います。


ryo-kun  2004-04-08 11:19:06  No: 8265

にしのさん,ご返答ありがとうございます.
計算途中で分母が1e-12以下になるからですか..

腑に落ちないことがありますので,
もう一つ質問させていただけますでしょうか?
今まで自前のルーチンを使っていたのですが,
そちらを使っている限りでは,エラーは出ないんです.
以下のようにして,

  cdiv(cmake(1,0),cmake(1e-10,1e-10))

は通ります.
やはり計算途中で分母は1e-12以下にはなっているんですが,
これがOKで,Delphi6の複素数が駄目なのは,
Variant 型の計算になにか特殊な事情があるんでしょうか?

type
   TComplex=record
     r:double;
     i:double;
   end;

function cmake;
var
   ctemp:Tcomplex;
begin
     ctemp.r:=r;
     ctemp.i:=i;
     result:=ctemp;
end;

function cdiv;
begin
  result:=cmake((c1.r*c2.r+c1.i*c2.i)/(c2.r*c2.r+c2.i*c2.i),
                (-c1.r*c2.i+c1.i*c2.r)/(c2.r*c2.r+c2.i*c2.i))
end;


にしの  2004-04-08 18:22:08  No: 8266

cdivの中で、機械イプシロン以下のチェックをしていないからです。
Delphiでは、分母が機械イプシロン以下かどうかを、IsZeroで判定しています。
特殊といえば、IsZero判定が特殊ということになりますね。
この場合、除数が機械イプシロン以下になった場合の除算結果が桁落ちして誤差が著しく現れることがあります。


にしの  2004-04-08 18:22:56  No: 8267

追記。
上の「この場合」とは、IsZeroの判定がない場合のことです。


ryo-kun  2004-04-09 08:18:31  No: 8268

にしのさん,丁寧なご説明ありがとうございました.
除数の値に細工することで対応しようと思います.


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加