ダブルの計算が上手くいかず悩んでいます。
a_Dが2053.22だと以下の変換ではa_iが2053219に変換されてしまいます。
その他の数字でどの数字がこういった現象になるかは、いろいろ試した結果
確認されていません。
a_D := a_D*power(10,3);
a_i := Trunc(a_D);
なぜこのような数字になるのでしょうか?
宜しくお願いします。
>なぜこのような数字になるのでしょうか?
最後の桁を「切り捨て」すると、1減ることがあるのは浮動小数点演算の宿命かな。
1000倍した時に
2053220.00000000.....
ではなくて
2053219.99999999.....
になっているんでしょうね。
これがいやなら、Double型ではなく、誤差を出来るだけ小さくした Currency型を使うべきでしょう。
はむれっとさん回答ありがとうございます。
そうなんですね〜。
ただ一部
a_i := Trunc(a_D);
を
a_i := StrtoInt(FloattoStr(a_D));
に変更したらうまくいきました。
Truncだと何かやってるんですかね?
ただこういった現象が、変更後によって全部の数字に対して回避できるのか不安です。
どのように対処しようか悩んでいます。。
それは、Delphi というより、すべての実数計算には誤差がつきものだ、という
当たり前のことを理解してないからです。回避する、とかの問題ではありません。
数値を限られたビット数で表す限り、実数計算の誤差は本質的なことです。
var a_D: Double; ではなく
var a_D: Externded; とするとa_iは2053220となるので
function Trunc(X: Extended): Int64; で Extendedに変換される時に誤差が現れる様ですね。
Truncで切り捨てをするなら Trunc(a_D+0.5); の様に四捨五入しても場合によっては良いと思います
var a_D: Extended;
書きミス
> a_i := StrtoInt(FloattoStr(a_D));
>に変更したらうまくいきました。
>Truncだと何かやってるんですかね?
実数を文字列に変換するルーチンでは四捨五入で数値を丸めているので、Trunc の返す値と異なる場合があるということ。
四捨五入でいいのなら、Round関数を使いましょ。
Trunc の返す値と Roundの返す値が異なる場合、
どっちを選ぶかユーザーに問い合わせてみる?
それとも、それをDebugログに記録しておく?
ちょうど調べてる最中に気になるのみ付けたので書き込みます。
>四捨五入でいいなら,Round関数を使いましょ。
Round関数では四捨五入にはなりません。あくまで丸めるだけの関数の模様です。
ttp://www2.big.or.jp/~osamu/Delphi/tips.cgi?index=0073.txt
ツイート | ![]() |