关于round:c#中round float/double型

float/double Math.Round in C#

本问题已经有最佳答案,请猛点这里访问。
1
2
3
4
5
6
7
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这就是为什么

1
Math.Round(ff, 1, MidpointRounding.AwayFromZero);

等于

1
Math.Round((double)ff, 1, MidpointRounding.AwayFromZero);

如果我们检查(double)ff

1
Console.Write(((double)ff).ToString("R"));

我们将看到行动中的错误汇总

1
31.149999618530273

最后,Math.Round(31.149999618530273, 1, MidpointRounding.AwayFromZero) == 31.1如预期


在浮点运算中,所有数字在内部都用分数表示,分母是2的幂。

(这是一个类似的方法,小数实际上是10次方分母的分数。因此,31.15只是一种写分数3115/100的方法。

在浮点中,31.15必须在内部表示为二进制数。最接近的二进制分数是:1111.1001001100110011001100110011001100110011001100110011001100...repeating

1100重复出现(永远重复),因此该数字将根据存储在double还是float中而被截断。在浮点数中,它被截断为24位,在双精度数中被截断为53位。

1
2
3
Exact:  1111.100100110011001100110011001100110011001100110011001100110011001100...forever
Float:  1111.10010011001100110011
Double: 1111.1001001100110011001100110011001100110011001100110

因此,可以看到这个数字转换成的双精度数实际上比它转换成的浮点数稍大。很明显,它不一定四舍五入到相同的数字,因为它不是以相同的数字开始的。