C# 浮点/双精度数学。用C进行四舍五入#
frst:31.1 drst:31.2C# 浮点/双精度数学。用C进行四舍五入#,c#,floating-point,double,rounding,C#,Floating Point,Double,Rounding,frst:31.1 drst:31.2 有人能解释一下原因吗?好吧,数学。Round想要双倍的,而不是浮动的,这就是原因 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); 等于 Math.Round(ff, 1
有人能解释一下原因吗?好吧,
数学。Round
想要双倍的,而不是浮动的,这就是原因
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);
等于
Math.Round(ff, 1, MidpointRounding.AwayFromZero);
如果我们检查(双)ff
值
Math.Round((double)ff, 1, MidpointRounding.AwayFromZero);
我们将看到行动中的汇总错误
Console.Write(((double)ff).ToString("R"));
最后,Math.Round(31.14999618530273,1,中点舍入.AwayFromZero)==31.1
如预期的那样,在浮点中,所有数字在内部表示为分数,分母为2的幂
(这与小数实际上是分母为10的幂的分数的方式类似。因此31.15
只是一种写分数的方式3115/100
)
在浮点运算中,31.15
必须在内部表示为二进制数。最接近的二进制分数是:1111.10010011001100…重复
1100
递归(永远重复),因此该数字将被截断,具体取决于它是存储在double还是float中。在浮点运算中,它被截断为24位,在双精度运算中,它被截断为53位
31.149999618530273
因此,您可以看到这个数字转换成的double实际上略大于它转换成的float。因此很明显,它不一定会四舍五入到同一个数字,因为它的开头不是同一个数字。因为(float)31.15
不等于(double)31.15
。浮点运算总是会产生舍入误差。在特殊舍入中,双精度舍入与浮点舍入不同。浮点值舍入错误是不可避免的。它们就像死亡和税收一样不可避免:@i486好吧,不总是这样,存在float
是有原因的。@i486同样,这并不意味着你永远不应该使用float
。C#gold徽章在哪里?IMHO本应在前17秒,而不是5小时后,作为dup关闭此文件!我很好奇为什么(double)ff
就是31.1499961853027
,而不是31.1500000000000
@Gonzalo Lorieto:double
是二进制的,0.15==15/100=3/20
是二进制表示中的周期分数。@gonzalorieto@gonzalorieto@gonzalorieto你可以在这里读到->
Exact: 1111.100100110011001100110011001100110011001100110011001100110011001100...forever
Float: 1111.10010011001100110011
Double: 1111.1001001100110011001100110011001100110011001100110