float ff = (float)31.15;
double dd = 31.15;
var frst = Math.Round(ff, 1, MidpointRounding.AwayFromZero);
var drst = Math.Round(dd, 1, MidpointRounding.AwayFromZero);
frst:31.1
最初:31.2
誰かが理由を説明できますか?
そうですね、_Math.Round
_はdouble
ではなくfloat
を必要としています。そのため、
_Math.Round(ff, 1, MidpointRounding.AwayFromZero);
_
等しい
_Math.Round((double)ff, 1, MidpointRounding.AwayFromZero);
_
そして、_(double)ff
_値を検査すると
_Console.Write(((double)ff).ToString("R"));
_
丸めエラーが表示されます
_31.149999618530273
_
最後に、期待どおりMath.Round(31.149999618530273, 1, MidpointRounding.AwayFromZero) == 31.1
浮動小数点では、すべての数値は、分母が2の累乗である分数として内部的に表現されます。
(これは、小数が実際に10の累乗の分母を持つ分数であるのと同様の方法です。したがって、31.15
は、分数を書くための方法です3115/100
)
浮動小数点では、31.15
は、内部的に2進数として表現する必要があります。最も近い2進数は次のとおりです:1111.1001001100110011001100110011001100110011001100110011001100...repeating
1100
繰り返します(永久に繰り返されます)。したがって、数値は、doubleに格納されているか、floatに格納されているかに応じて切り捨てられます。 floatでは24桁に切り捨てられ、doubleでは53桁に切り捨てられます。
Exact: 1111.100100110011001100110011001100110011001100110011001100110011001100...forever
Float: 1111.10010011001100110011
Double: 1111.1001001100110011001100110011001100110011001100110
したがって、この数値が変換するdoubleは、実際には変換するfloatよりわずかに大きいことがわかります。そもそも同じ数ではないため、必ずしも同じ数に丸められるわけではないことは明らかです。