- - PR -
四捨五入
投稿者 | 投稿内容 | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
投稿日時: 2003-07-29 15:47
C#では double -> long のキャストは切捨て(ゼロに向かって最も近い整数値への丸め)です。 http://www.microsoft.com/japan/msdn/library/ja/csspec/html/vclrfcsharpspec_6_2_1.asp
この例で私が意図していたのは、 「精度の高いdoubleを使用していても、ごく単純な演算とMath.Round()の組み合わせで あっという間に誤差が膨れ上がってしまう」 ということです。 ですから、最初の > Console.WriteLine(value); でどんな値が出力されるかについてはあまり気にしていません。 | ||||||||||||
|
投稿日時: 2003-07-29 16:37
unibon です。こんにちわ。
すみません。途中で言語が C# に変わっていたことに気づきませんでした。 (余談ですが VB.NET だとほぼ VB/VBScript と同じようでした。 http://www.microsoft.com/japan/msdn/library/ja/vbls7/html/vblrfVBSpec10_4_1.asp )
演算の過程で誤差が生じるのではなく、 演算の対象として例示された値(10000000000049999)が、 演算前に、すでに double で表現できる整数の範囲を 超えていることがもっとも大きな要因だと思います。 この値を表現するには約53.15ビット必要ですが、 double の仮数部のビット数は53ビットです。 | ||||||||||||
|
投稿日時: 2003-07-29 17:28
??? ここで私が言及しているのは、 // おまけ: 0.1を55回加算してからRound() 以降の部分についてですよ。 | ||||||||||||
|
投稿日時: 2003-07-29 18:42
>> わたしの場合、浮動小数点型をdoubleに統一することで回避しています。
> という発言が「全てdoubleを使っていれば浮動小数点の誤差も気にしなくてよい」という >誤解を招きかねないと思ってのものです。 たしかに、多数の方々に誤解を招いているようで...失礼しました。 完璧な実装をするならば、(COBOLの処理方法の様に)文字列操作で演算させるしか 無いのではと思っています。 そこまで実装するのは大変で...ということであれば、有効桁数を意識するしかないのでしょうね。 (有効桁数を意識しながら、四捨五入を2回行うとか...←完璧ではありません! 誤解の無いようにお願いします。) | ||||||||||||
|
投稿日時: 2003-07-29 18:55
unibon です。こんにちわ。
#すみません。かなり昔に戻ります。
そのやり方に問題はないはずです。 反例(正しくない値になってしまうこと)はないと思います。 もちろん使う道具(double や float)が持つビット数の制限を 越えない範囲内で使うという前提はあります。 C# (や VB.NET) の仕様では、整数を扱えるビット数の幅が、 float < int < double < long なので、double を使うよりは long を使ったほうが、 扱える数値の範囲が広くて有利ですが、 それはたまたまそういうビット数に決まっているだけであり、 浮動小数点型の double だから理論的な誤差がある、というわけではないです。 もし long がなかったら double のほうが有利です (有利・不利はあくまでも扱える数値の範囲だけであり、誤差の有無とは別です)。 #なお、ここでは、あくまでの「そのやり方」(MyRound の実装)について書いています。 #0.1 を 55 回加算するのはまた別です。
すみません。論点を勘違いしていました。 | ||||||||||||
|
投稿日時: 2003-07-29 18:57
> 完璧な実装をするならば、(COBOLの処理方法の様に)文字列操作で演算させるしか
> 無いのではと思っています。 > そこまで実装するのは大変で...ということであれば、有効桁数を意識するしかないのでしょうね。 > (有効桁数を意識しながら、四捨五入を2回行うとか...←完璧ではありません! 誤解の無いようにお願いします。) と書いたものの...さらなる誤解を招くと良くないので... すみませんが、無視してください。 有識者の方々のご意見を頂きたいと思います。 | ||||||||||||
|
投稿日時: 2003-07-29 19:09
なんか、いつの間にかふくれあがっていますね。
「誤差」の問題は、実数を扱うシステムでは常に意識しておかなければならない問題ですね。その点で、yamasaさんのご指摘の『「5万を加えて、10万で割り(int型のまま)、10万倍する」』は、確かにその通りです。できる限り整数で演算するように、頭を持っていかなければなりませんでした。「精度」には気を遣っているのですが、「誤差」は抜けていました。 ところでdamepgさん、int32では21億4748万3647が最高値です。これ以上の数値にはならないことが保証されているのでしょうか?「万の位」というところから、どれくらいの数値を扱うのか、気になりました。 なちゃさんの『この辺は意外に(どころか全く)知らない人も結構いてびっくりしたりしますね。』が、大変気になりました。私も入社当時、地図の回転縮小で「誤差」に苦しみました。忘れるとは、苦しみ方が甘かったようです。 | ||||||||||||
|
投稿日時: 2003-07-29 19:57
unibon です。こんにちわ。
どこかの掲示板で見かけたのですが、
のようなやりかたもあるそうです。 #「へぇ〜」度が高いですよね。 #こちらの掲示板だったかもしれませんが、良く覚えていません。 #以下、あとで追加。 あれ、これは四捨五入じゃなくて切捨てでした。 四捨五入にも応用できるんでしょうか。 [ メッセージ編集済み 編集者: unibon 編集日時 2003-07-29 20:00 ] |