c# - 对于 c# 中的正数,转换为 Int 返回与 FloorToInt 不同的值
问题描述
[编辑]我按照评论的内容重写了整个示例。
float value = 0.52631580f;
float sum = 0;
for (int i = 0; i < 10; i++)
{
float division = sum / value;
int result = (int)division;
Console.WriteLine(division.ToString("0.00000") + " - " + result.ToString("0.00000"));
sum += value;
}
结果不是预期的:
0,00000 - 0,00000
1,00000 - 1,00000
2,00000 - 2,00000
3,00000 - 3,00000
4,00000 - 4,00000
5,00000 - 5,00000
6,00000 - 5,00000 <---- It should be 6
7,00000 - 7,00000
如果我手动执行, (int)6.00000000000f <-- 当然返回 6。
这怎么可能?
解决方案
代码是对的。并且符合标准。我WriteLine
将这一行改为:
Console.WriteLine($"{sum:0.000} {value:0.000} {division:N18} - {result:0.00000}");
并得到
2.105 0.526 4.000000000000000000 - 4.00000
2.632 0.526 5.000000000000000000 - 5.00000
3.158 0.526 5.999999523162841797 - 5.00000
3.684 0.526 6.999999523162841797 - 6.00000
4.211 0.526 7.999999046325683594 - 7.00000
4.737 0.526 8.999999046325683594 - 8.00000
舍入错误意味着除法结果不完全是 6、7 或 8。只有 5 位数字,我得到:
3.158 0.526 6.00000 - 5.00000
3.684 0.526 7.00000 - 6.00000
4.211 0.526 8.00000 - 7.00000
4.737 0.526 9.00000 - 8.00000
这与 C# 如何截断或舍入无关,而是关于浮点数的格式。符合 IEEE 标准的方法是在格式化时四舍五入到所需的精度。
呼——有那么一会儿,我实际上忘记了我对花车的了解。
PS:在 .NET Core 3 中引入了另一个有趣的 15 位数字变化。在此之前,字符串格式化停止生成 15 位数字,这导致与接近但不完全等于整数的值相当混乱。
从 .NET Core 3 开始,字符串格式化程序会发出足够的数字来生成the shortest roundtrippable string
. 使用
Console.WriteLine($"{division} - {result}");
生产:
4 - 4
5 - 5
5.9999995 - 5
6.9999995 - 6
7.999999 - 7
8.999999 - 8
这就是为什么他们在计算数学时教我们永远不要比较浮点数是否相等,而只检查绝对差是否低于阈值。
我总是忘记并且在崩溃或无限循环之后必须重新发现的东西。
PPS:舍入误差
产生小数位是因为float
没有足够的精度来存储sum
或division
不进行舍入。
使用$"{sum} {division} - {result}"
和切换 from float
todouble
只产生一个带小数位数的结果:
3.1578948 6 - 6
3.6842105999999997 6.999999999999999 - 6
4.2105264 8 - 8
请注意,甚至sum
有舍入错误。
仅decimal
具有足够的精度来存储准确的结果并避免舍入误差:
2.63157900 5 - 5
3.15789480 6 - 6
3.68421060 7 - 7
4.21052640 8 - 8
4.73684220 9 - 9
推荐阅读
- reactjs - TypeScript 与 Luxon 的兼容性
- apache-spark - 无法在 PySpark 中按多行获得平均值和标准差
- python - 隐藏的输入字段未显示从 Django 中的 views.py 访问的正确值
- python - 在工厂函数和动态继承之外定义类
- ios - Apple 是否支持使用 .net mvc5 或 webapi2 进行外部登录
- html - 如何从两端缩短底部边框?
- pythonanywhere - 在 pythonanywhere 中部署 django 应用程序时出错
- python - 赋值前引用的 Tkinter 变量“Num1”
- python-3.x - 如何使用 pandas 以 csv 格式将每个数组存储在不同的列中?
- php - WordPress如何在我的自定义页面中显示function.php文件中的变量值?