こんにちは,はじめまして.
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 です
1E-10の計算途中に、2E-20となり、機械イプシロンの1E-12より小さくなるためゼロと判断されます。
複素数の除算の数式を参考にされると、解決するかと思います。
にしのさん,ご返答ありがとうございます.
計算途中で分母が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;
cdivの中で、機械イプシロン以下のチェックをしていないからです。
Delphiでは、分母が機械イプシロン以下かどうかを、IsZeroで判定しています。
特殊といえば、IsZero判定が特殊ということになりますね。
この場合、除数が機械イプシロン以下になった場合の除算結果が桁落ちして誤差が著しく現れることがあります。
追記。
上の「この場合」とは、IsZeroの判定がない場合のことです。
にしのさん,丁寧なご説明ありがとうございました.
除数の値に細工することで対応しようと思います.
ツイート | ![]() |