2014/10/8 (水) 16:52:07 Mr.XRAY |
>今度は,64 ビットのEXE を作成して実行してみます.
>やはり,e と f の表示が違います.
当サイトに次のような記事があります.
これとも関係してきます.
[890_計算誤差 ( 数値計算の誤差 ) と多倍長演算]
http://mrxray.on.coocan.jp/Delphi/plSamples/890_CalcError.htm
サンプルの
e:=(a+b+c)*d; //(1)
f:=a*d+b*d+c*d; //(2)
e と f の値は,数学的には同じでも,コンピュータ内部では異なる場合があります.
FloatToStr 関数は,数値を文字列にする際,15 桁で丸めます.
一方,SimpleRoundTo 関数は,元の値を使用して四捨五入します.
このことを利用すると,数値を一度 FloatToStr 関数で文字列にして,
再度実数にすれば,16 桁以上の精度があれば,計算結果の違いを回避すること
ができることになります.
今回のような単純な計算であれば利用可能でしょう.
そのテスト用コードです.
//-----------------------------------------------------------------------------
// (1)と(2)の計算式は,数学的には等しく,179.935となる
//-----------------------------------------------------------------------------
procedure TForm1.Button1Click(Sender: TObject);
var
a,b,c,d,e,f:Extended;
strText : String;
begin
a:=389.7;
b:=94.4;
c:=30;
d:=0.35;
e:=(a+b+c)*d; //(1)
f:=a*d+b*d+c*d; //(2)
//StrToFloatは15桁で丸めを行うので15桁に丸めた文字列を取得する
//その文字列を再度実数にする
e := StrToFloat(FloatToStr(e));
f := StrToFloat(FloatToStr(f));
StrText := FloatToStr(e)+#13+
FloatToStr(f)+#13+ sLineBreak +
FloatToStr(SimpleRoundTo(e,-2))+#13+
FloatToStr(SimpleRoundTo(f,-2));
MessageBox(Handle, PChar(strText), '結果', MB_OK);
end;
下図が実行結果です.
指定小数点以上の精度が必要ないか,計算の結果の精度が分かっている場合,
次のように,計算の結果をその小数点の桁数に四捨五入してしまう方法も
考えられます.
e := SimpleRoundTo(e, -10);
f := SimpleRoundTo(f, -10);
この他,FloatToStrF 関数, FloatToText 関数 や FloatToTextFmt 関数で,
精度を指定する方法もあります.
FloatToStrF(f, ffFixed, 10, 2))
は,10 桁の精度で,固定小数点形式の小数点 2 桁までの値の文字列を取得します.
[System.SysUtils.FloatToStrF - RAD Studio API Documentation]
http://docwiki.embarcadero.com/Libraries/XE6/ja/System.SysUtils.FloatToStrF
|
|