喫茶XRAYトップページ


[8406] Format関数を使ったときの数値の丸めについて返信 削除
2015/1/22 (木) 15:56:17 おかぽん
こんにちは

例えば、次のようにFomat関数を使用します。
Format('%9.3f', [123.456789])

結果として、'  123.457' が返りますが、この小数点以下4桁目の丸めの仕様について
記載されたページをご存じないでしょうか?

Roundで丸めた結果と同じかどうかが知りたいのです。

ここを見ても、精度がどうこうしか記載がありません。
http://docwiki.embarcadero.com/Libraries/XE7/ja/System.SysUtils.Format

SysUtilsのソースを見て、FloatToTextに行き着いて・・・最終的には
CurrToDecimal関数を使っていそうな気分にはなってきましたが、
中身はアセンブラで、理解することをあきらめてしまいました。

ステップ実行で追いかけても、アセンブラが読めなくて、どうなっているのか
さっぱりわからなかったんです。



[8407] Re:Format関数を使ったときの数値の丸めについて返信 削除
2015/1/22 (木) 16:28:43 Mr.XRAY
▼ おかぽんさん.どうもです.

> 結果として、'  123.457' が返りますが、この小数点以下4桁目の丸めの仕様について
> 記載されたページをご存じないでしょうか?


う〜ん,私は知らないです.
ちょっと考えると,ないのが不思議な気もしますが.
あまり考えないで使っちゃっていますね (^^;

> SysUtilsのソースを見て、FloatToTextに行き着いて・・・最終的には
> CurrToDecimal関数を使っていそうな気分にはなってきましたが、


根性ですね (^^;
後で私も挑戦してみようかな?


[8409] Re2:Format関数を使ったときの数値の丸めについて返信 削除
2015/1/22 (木) 16:50:42 おかぽん
▼ Mr.XRAYさん
> あまり考えないで使っちゃっていますね (^^;
同じく、考えないで使っていましたが、帳票でFormatを使った結果を表示して
いましたが、諸事情により、その値を数値として使う必要が出てきました。

Format関数で文字列化しているので、StrToFloatとかで実数かでもいいんですが、
元の値として、丸める前の実数値を持っているので、数値→文字列→数値というのも
かっこわるいし、ちょっとのことで、コストかかるかなと。

それなら単純にRound関数で丸めるほうがすっきりするので、念のため確信を
得てからにしようと思ったわけなんですけど。


今時のPCは十分早いので、とりあえずは文字列から数値に戻す方向で検討中。

気になるとこなので、苦手な英文サイトも読まないと(読んでわかったフリするだけ)。

[8408] Re:Format関数を使ったときの数値の丸めについて返信 削除
2015/1/22 (木) 16:33:04 おかぽん
FloatToTextですが、さては、FPU丸めモードに従って丸められるだけかな?
FRNDINT を使っているようなので。

参考資料:http://exlight.net/devel/x86/fpu/

[8410] Re2:Format関数を使ったときの数値の丸めについて返信 削除
2015/1/22 (木) 18:05:18 Mr.XRAY
▼ おかぽんさん

> FloatToTextですが、さては、FPU丸めモードに従って丸められるだけかな?
> FRNDINT を使っているようなので。
>
> 参考資料:http://exlight.net/devel/x86/fpu/


なるほど,FPU の演算仕様を調べればいいということですね.


[8414] Re3:Format関数を使ったときの数値の丸めについて返信 削除
2015/1/23 (金) 10:18:02 おかぽん
▼ Mr.XRAYさん
> なるほど,FPU の演算仕様を調べればいいということですね.
わからないアセンブラを、ステップ実行してみたところ、そうではなさそうです。

ソースがあって実行可能な環境が Delphi 5 しかない状態ですが、

Format 関数は 以下の順で呼び出しされます。
FmtStr→FormatBuf→FloatToText→FloatToDecimal→ExtToDecimal

ExtToDecimalがおそらく丸めを行っているとこなんですけど、以下は
アセンブラが読めなくて苦しいため、正しいかどうかわかりません。

丸める値が "0.005499999232" (現在やりたい処理に相当する適当な値)とすると、
まず 指定された値 0.005499999232に1E18を乗じて5.499999232E18
FRNDINT は、ここで使用されているので、先の投稿は間違い。

以降は、一文字ずつ文字列化している処理しています。
STOSWやらSTOSBで、どこにいったかわからない文字列orz
でも、以降の処理を読む限り、丸める桁の値が5であれば、一つ前の桁を1増やしてる。
銀行型のRound関数とは異なる丸め。
実際、0.065 → 0.07、0.075 → 0.08、-0.065 → -0.07、-0.075 → -0.08 となり
間違いなさそう。

なんてこったい。

[8415] Re4:Format関数を使ったときの数値の丸めについて返信 削除
2015/1/23 (金) 10:40:11 おかぽん
とりあえず、ExtToDecimal関数については、Delphi 5 と Delphi 7 は、
多少記述が違うけど、丸めの部分は同じ。
Turbo Delphi は、Delphi7と全く同じ。
以降のバージョンは、ソースがないのでわかりません。

[8417] Re5:Format関数を使ったときの数値の丸めについて返信 削除
2015/1/23 (金) 21:02:40 Mr.XRAY
▼ おかぽんさん

> とりあえず、ExtToDecimal関数については、Delphi 5 と Delphi 7 は、
> 多少記述が違うけど、丸めの部分は同じ。
> Turbo Delphi は、Delphi7と全く同じ。
> 以降のバージョンは、ソースがないのでわかりません。


多分、おそらく、他のバージョンの Delphi も同じだと思いますてけどね


INCM/CMT
Cyclamen v3.82