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);
首先: 31.1
其次: 31.2
有人能解释一下为什么吗?
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);
首先: 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
(按预期)
(double)ff
的值确切为31.14999961853027
而不是31.150000000000000
。 - Gonzalo Lorieto在浮点数中,所有数字在内部都表示为分母为2的幂次方的分数。
(这类似于十进制实际上是具有10的幂作为分母的分数。因此,31.15
只是写作分数3115/100
的一种方式)
在浮点数中,31.15
必须在内部表示为二进制数。最接近的二进制分数是:1111.1001001100110011001100110011001100110011001100110011001100...重复
1100
会不断循环(重复),因此根据是否存储在双精度或单精度中,该数字将被截断为不同的长度。在单精度中被截断为24位数字,在双精度中则为53位。
Exact: 1111.100100110011001100110011001100110011001100110011001100110011001100...forever
Float: 1111.10010011001100110011
Double: 1111.1001001100110011001100110011001100110011001100110
因此,您可以看到这个数字转换成的双精度浮点数实际上比它转换成的单精度浮点数稍微大一些。因此很明显它不一定会四舍五入为相同的数字,因为它本身就不是相同的数字。
因此,您可以看到这个数字转换成的双精度浮点数实际上比它转换成的单精度浮点数稍微大一些。因此很明显它不一定会四舍五入为相同的数字,因为它本身就不是相同的数字。
(float)31.15
不等于(double)31.15
,浮点数运算几乎总会产生舍入误差。特别是双精度浮点数的舍入与单精度浮点数不同。 - MakePeaceGreatAgainfloat
。 - SᴇM