2016-06-25 7 views
-1

私は7桁まで数値を丸めるしようとしていますが、私は恐らくMath.roundは、いくつかの数字で正常に動作しないことに気づいた:C#Math.Roundバグ?

Math.Round(39.248779999999996,3) => 39.249 
Math.Round(39.248779999999996,4) => 39.2488 
Math.Round(39.248779999999996,5) => 39.248779999999996 
Math.Round(39.248779999999996,6) => 39.248779999999996 
Math.Round(39.248779999999996,7) => 39.248779999999996 

誰も私にこの動作を説明できますか?

+7

これらは浮動小数点値であり、 。彼らは、任意の桁数を持つ有限バイナリ表現を持っていません。正確な表現が必要な場合は、 'decimal'型に変換してください。 –

+0

問題は、メソッドのシグネチャを変更できないために外部コンポーネントにdoubleを渡す必要があり、その番号に小数点以下7桁がある場合、そのコンポーネントはエラーをスローします。その倍数を小数点第7位まで効果的に丸める方法はありますか? – smeegoan

+0

ええと、倍精度浮動小数点型は丸められた値を格納する方法がないため、とにかく動作しませんでした。外部コンポーネントはバグです。ダブルスは小数点以下の桁数が固定されていません。 decimal型を使用しているはずです。 –

答えて

4

精度が必要な場合はで、double/floatではなく、

var num = 39.248779999999996; // num is double. 
var num = 39.248779999999996m; // num is decimal. 

小数キーワードは、128ビットのデータタイプを示します。 の浮動小数点型と比較して、小数点型の精度が高く、 の範囲が狭いため、財務および通貨の数値計算に適しています。

編集:

あなたは二重のフロート/に正確にすべての数値を表すcan't

2進浮動小数点演算は長い間、あなたが は何が起こっているのかを知っているとそうでないとして罰金です値は正確に小数点以下のものであることを期待してください。プログラムには を入れてください。正確な結果を得るためには、バイナリの 浮動小数点数を含む計算は期待しないでください。 2つの数字がどちらも使用しているタイプで正確に表現されていても、その2つの数字を含む操作の結果は であるとは限りません。これは、除算で最も簡単に見られます(例えば、 の1/10は、1と10の両方が表現可能ですが、 と表記できます)。例については

double doubleValue = 1f/10f; // => 0.10000000149011612 
decimal decimalValue = 1m/10m; // => 0.1 

あなたは7桁の最大を確保するために数字を切り捨てることができますが、正確に値がラウンドすることはできません。

double value = 39.248779999999996; 

double roundTo = Math.Pow(10, 7); 
double resultResult = Math.Truncate(value * roundTo)/roundTo; 
// result is : 39.2487799 
+0

問題は、メソッドのシグネチャを変更できないために外部コンポーネントにdoubleを渡す必要があり、その番号に小数点以下7桁がある場合、そのコンポーネントはエラーをスローします。その倍数を小数点第7位まで効果的に丸める方法はありますか? – smeegoan

+0

@smeegoanは上記の編集された答えをチェックします。 – user3185569

+0

私はそれを試み、結果は39.248779999999996に等しいままです。 Console.WriteLineを使用して結果を表示した場合は、デフォルトでは一般形式( "G")の書式指定子が使用されているので、Console.WriteLine(result.ToString( "r"));を使用してください(https:// msdn Microsoft。com/en-us/library/dwhawy9k.aspx#RFormatString) – smeegoan