C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[5]: 四捨五入の結果が異なる数値の謎


(過去ログ 112 を表示中)

[トピック内 8 記事 (1 - 8 表示)]  << 0 >>

■66584 / inTopicNo.1)  四捨五入の結果が異なる数値の謎
  
□投稿者/ moyamoya (1回)-(2013/05/09(Thu) 20:15:31)

分類:[.NET 全般] 

お世話になります。

小数点3位まであるdouble型の数値を小数点2位で四捨五入する処理を作成し、
動作確認の際に発見したのですが、他の値と四捨五入の結果が異なる特定の数値があります。

その値とは「4.895」で、小数点2位で四捨五入すると「4.90」にはならず、「4.89」になります。

「5.895」「3.895」「2.895」「1.895」等の数値を同様に四捨五入するとそれぞれ「5.90」「3.90」「2.90」「1.90」
になるのに、「4.895」の結果だけが異なるのです。

四捨五入に使ったのは、じゃんぬねっと様作成の関数「ToHalfAdjust」およびMath.Round関数に
MidpointRounding.AwayFromZeroを指定したものを使ってそれぞれ確認しましたが、いずれも結果は同じでした。

プログラム的な四捨五入の結果は一般的な四捨五入とは異なる事は承知していますが、数値によって結果が異なるのは
それ以前の問題と思いますので、何とか解決したいと思うのですが、原因と対策をご存知の方がおられましたら
どうぞよろしくお願いいたします。

一旦整数化するのが一番確実なんでしょうか・・・




引用返信 編集キー/
■66585 / inTopicNo.2)  Re[1]: 四捨五入の結果が異なる数値の謎
□投稿者/ 魔界の仮面弁士 (211回)-(2013/05/09(Thu) 21:51:16)
No66584 (moyamoya さん) に返信
> 小数点3位まであるdouble型の数値を小数点2位で四捨五入する処理を作成し、

四捨五入を目的としているのに、浮動小数点数で取り扱おうとしているのが、
そもそもの問題だったりします。
System.Single や System.Double ではなく、System.Decimal を使うべきです。

---

double 型は、内部値を 2 進小数として管理しています。

0.5 や 4.250 といった値は誤差なく格納できますが、
0.1 や 4.895 といった値は近似値として格納される型なのです。


1÷10 という値は、10進小数では .1 と表現できますよね。
しかし 2進小数であらわすと、.0001100110011001100110011…という循環小数になります。

1÷3 という値は、10進表現では .3333333…という循環小数になります。
しかし 3進小数であれば、.1 と表現できます。無限小数にはなりません。


桁数が無限に持てるのであれば正しい値となるのでしょうが、変数のサイズは有限です。
小数桁が長い値や、無限小数や循環小数などを扱うためには、有限桁で打ち切られて
格納することになり、結果として近似値で扱われることになります。

近似値ということは、本来の期待値よりも微妙に大きいまたは小さい値であるため、
10進数でいうところの特定の桁で丸める処理が、期待動作しなくなることがありえます。


10進数演算のために「そもそも double を使わない」ことです。
かわりに、10 進型である Decimal 型を使うようにしてください。


これは、double 型を Decimal 変換して使う…という意味ではありません。
最初から最後まで double を一切使わないということです。
引用返信 編集キー/
■66586 / inTopicNo.3)  Re[1]: 四捨五入の結果が異なる数値の謎
□投稿者/ shu (303回)-(2013/05/09(Thu) 21:52:48)
2013/05/09(Thu) 21:53:33 編集(投稿者)

No66584 (moyamoya さん) に返信
> お世話になります。
>
> 小数点3位まであるdouble型の数値を小数点2位で四捨五入する処理を作成し、
doubleを使用しているのが今回の原因です。Decimalにすればよいです。
この手の正確性を追求する場合、DoubleではなくDecimalを使用し細かい部分の
違いを追求しない場合にSingleとかDoubleを使うとよいです。


引用返信 編集キー/
■66589 / inTopicNo.4)  Re[2]: 四捨五入の結果が異なる数値の謎
□投稿者/ Azulean (157回)-(2013/05/09(Thu) 22:58:44)
念のため。
double を decimal に単純に置き換えると、double に比べて扱えない数値もありますのでご注意ください。

http://code.msdn.microsoft.com/windowsdesktop/4-decimal-doublefloat-4754c9ae
引用返信 編集キー/
■66598 / inTopicNo.5)  Re[2]: 四捨五入の結果が異なる数値の謎
□投稿者/ moyamoya (2回)-(2013/05/10(Fri) 13:32:57)
皆様、回答ありがとうございました。

Double型同士の演算で微小誤差が出るのは認識していて、その分は四捨五入すればいい・・・と
思っていたのですが、四捨五入自体が正確にできないというのは初めて知りました。
Decimal型を使って対応する事にします。ありがとうございました。
引用返信 編集キー/
■66606 / inTopicNo.6)  Re[3]: 四捨五入の結果が異なる数値の謎
□投稿者/ moyamoya (3回)-(2013/05/10(Fri) 18:30:41)
解決済みチェックを忘れていました。
解決済み
引用返信 編集キー/
■66616 / inTopicNo.7)  Re[4]: 四捨五入の結果が異なる数値の謎
□投稿者/ ロートルプログラマ (1回)-(2013/05/11(Sat) 21:09:52)
毎度のご活躍、尊敬申し上げます>魔界の仮面弁士さま

>四捨五入を目的としているのに、浮動小数点数で取り扱おうとしているのが、
>そもそもの問題だったりします。

ちゃちゃを入れさせていただきます。この表現はいささか正確性を欠くと
思います。
「四捨五入を目的としているのに、2進数浮動小数点数で取り扱おうとしているのが」
だと思います。10進数浮動小数点数であれば別に問題はありませんから。



引用返信 編集キー/
■66617 / inTopicNo.8)  Re[5]: 四捨五入の結果が異なる数値の謎
□投稿者/ ロートルプログラマ (2回)-(2013/05/11(Sat) 21:19:37)
やっぱいらぬチャチャでした。解決済みチェック。
解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -