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跨度
有人可以解释为什么?
- 因为(float)31.15不等于(double)31.15。浮点算术通常都会产生舍入误差。在空间成圆中,双精度的工作方式不同于成圆浮点数。
- 不要使用float。始终为decimal或double。
- 对于浮点值,舍入误差是不可避免的。它们和死亡和税收一样不可避免:youtube.com/watch?V= PZRI1IFSTO0
- @I486好吧,不总是,有一个原因,为什么float存在。
- @sem float存在于c中,主要是为了与c兼容。在c中,它在嵌入式系统中很重要,或者在RAM大小有限的旧PC中很重要。假设您有256KB(不是MB)并且需要实数数组-每个float值需要4个字节,而double需要8个字节。
- @再说一遍,这并不意味着你不应该使用float。
- @扫描电镜几乎"从未"在C。或者至少对于每一个经验不足的程序员来说,这是一个简单的规则。
- @himbrombere (float)31.15是一个转换为float的双值,它会导致双舍入误差,可能与31.15f不同(在float precision中,该值最接近31.15),为什么需要在float文本中指定"f"?,为什么比较double和float会导致意外的结果?,比较float和float-literal的奇怪输出
- 另一个副本:浮点数学是否已损坏?
- @i486浮点在许多情况下仍然有用,特别是在数组中。它将所需的带宽减半,这是许多应用程序的瓶颈,在这些应用程序中,精度实际上并不重要,这就是为什么在成像或人工智能中,它们甚至使用16位浮点
- @phuclv,这是c?或者c.如果double数组是瓶颈,那么clr/c也是瓶颈。我在上面提到过,对double的建议是针对初学者的——第一次避免float(多年的编程)。
- @I486它不仅仅是内存(双倍占用空间),它还包括速度、3D图形的矢量化(四个浮点数适合128位矢量)等。为您的需要选择正确的数据类型很重要,而不是忽略整个数据类型。
- C金徽章在哪里?天哪,这本应该在前17秒,而不是5小时后,以dup的形式关闭!
好吧,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")); |
我们将看到行动中的错误汇总
最后,Math.Round(31.149999618530273, 1, MidpointRounding.AwayFromZero) == 31.1如预期
- 我很好奇为什么(double)ff是31.14999961853027而不是31.150000000000000。
- @Gonzalo Lorieto:double是二进制的,0.15 == 15 / 100 = 3 / 20是二进制表示中的周期分数。
- @gonzaloorieto stackoverflow.com/questions/618535/…
- @你可以在这里读到它->浮点运算
在浮点运算中,所有数字在内部都用分数表示,分母是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 |
因此,可以看到这个数字转换成的双精度数实际上比它转换成的浮点数稍大。很明显,它不一定四舍五入到相同的数字,因为它不是以相同的数字开始的。