Doubleの計算について


とも  2006-03-02 02:23:07  No: 20284

ダブルの計算が上手くいかず悩んでいます。
a_Dが2053.22だと以下の変換ではa_iが2053219に変換されてしまいます。
その他の数字でどの数字がこういった現象になるかは、いろいろ試した結果
確認されていません。

    a_D := a_D*power(10,3);
    a_i := Trunc(a_D);

なぜこのような数字になるのでしょうか?
宜しくお願いします。


はむれっと  2006-03-02 03:28:48  No: 20285

>なぜこのような数字になるのでしょうか?
最後の桁を「切り捨て」すると、1減ることがあるのは浮動小数点演算の宿命かな。
1000倍した時に
2053220.00000000.....
ではなくて
2053219.99999999.....
になっているんでしょうね。
これがいやなら、Double型ではなく、誤差を出来るだけ小さくした Currency型を使うべきでしょう。


とも  2006-03-02 17:55:48  No: 20286

はむれっとさん回答ありがとうございます。
そうなんですね〜。

ただ一部
  a_i := Trunc(a_D);

  a_i := StrtoInt(FloattoStr(a_D));
に変更したらうまくいきました。
Truncだと何かやってるんですかね?
ただこういった現象が、変更後によって全部の数字に対して回避できるのか不安です。
どのように対処しようか悩んでいます。。


えーと  2006-03-02 20:00:59  No: 20287

それは、Delphi というより、すべての実数計算には誤差がつきものだ、という
当たり前のことを理解してないからです。回避する、とかの問題ではありません。

数値を限られたビット数で表す限り、実数計算の誤差は本質的なことです。


ふむ  2006-03-02 20:10:57  No: 20288

var a_D: Double; ではなく
var a_D: Externded; とするとa_iは2053220となるので
function Trunc(X: Extended): Int64; で Extendedに変換される時に誤差が現れる様ですね。
Truncで切り捨てをするなら Trunc(a_D+0.5); の様に四捨五入しても場合によっては良いと思います


ふむ  2006-03-02 20:12:53  No: 20289

var a_D: Extended; 
書きミス


それはね…  2006-03-02 20:26:06  No: 20290

>  a_i := StrtoInt(FloattoStr(a_D));
>に変更したらうまくいきました。
>Truncだと何かやってるんですかね?

実数を文字列に変換するルーチンでは四捨五入で数値を丸めているので、Trunc の返す値と異なる場合があるということ。
四捨五入でいいのなら、Round関数を使いましょ。


あの手この手、ダレの手?  2006-03-02 20:32:27  No: 20291

Trunc の返す値と Roundの返す値が異なる場合、
どっちを選ぶかユーザーに問い合わせてみる?
それとも、それをDebugログに記録しておく?


Ru  2006-03-10 00:30:08  No: 20292

ちょうど調べてる最中に気になるのみ付けたので書き込みます。

>四捨五入でいいなら,Round関数を使いましょ。

Round関数では四捨五入にはなりません。あくまで丸めるだけの関数の模様です。

ttp://www2.big.or.jp/~osamu/Delphi/tips.cgi?index=0073.txt


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

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






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