浮動小数点の演算では演算誤差が出ることは以前に書きました。
[実数の計算誤差]
http://ht-deko.minim.ne.jp/delphiforum/?vasthtmlaction=viewtopic&t=1203
演算を BCD (Binary Code Decimal = 二進化十進数) で行えば誤差の問題は起こりにくくなります。BCD を扱う TBCD は FmtBCD で定義されています…ところが、Delphi で BCD を扱おうと思うと、
var i: Integer; Value1, Value2: TBCD; begin Value1 := DoubleToBCD(1.2345); Value2 := DoubleToBCD(0.12345); for i:=1 to 10 do BcdSubtract(Value1, Value2, Value1); if BcdCompare(Value1, IntegerToBCD(0)) = 0 then ShowMessage('Zero') else ShowMessage('Non Zero'); end;
見ての通り、演算子が使えません。とても面倒です。
しかしながら、XE2 以降だと BCD 演算が手軽に行えるようになっています。演算子のオーバーロードにより演算子が普通に使えるのです。実際のコードは以下のようになります。
var i: Integer; //Value1, Value2: Currency; Value1, Value2: TBCD; begin Value1 := 1.2345; Value2 := 0.12345; for i:=1 to 10 do Value1 := Value1 - Value2; if Value1 = 0 then ShowMessage('Zero') else ShowMessage('Non Zero'); end;
これならお手軽に使えますね。TBCD の変数を Currency (Double でもいいのですが) に変更すると "Non Zero" が返ってきますが、TBCD では、ちゃんと "Zero" が返ります。
# XE2 と同等の TBCD は Delphi 2006 以降で自作する事が可能です。
See Also:
[DelphiのBcdライブラリ (Team Japan)]
http://blogs.embarcadero.com/teamj/2009/06/15/518/
[ビットフィールドを操作する (Delphi 2006 以降...フル機能は 2009 以降)]
http://ht-deko.minim.ne.jp/tech076.html#tech133
|