我在 C# 代码中遇到了涉及浮点算术和整数类型转换的意外行为。这是代码的简化版本:
static void Main(string[] args)
{
int d0 = (int)(2.300000000000001 * 100D);
int d1 = (int)(2.3000 * 100D);
Console.WriteLine(d0);
Console.WriteLine(d1);
return;
}
在此代码中,d0 和 d1 都被赋予浮点乘法转换为整数的结果。
d0 和 d1 的预期结果应为 230。然而,虽然 d0 正确计算为 230,但 d1 却意外地得出 229。
我知道浮点运算有时会由于精度限制而引入小错误,但我无法解释为什么 d1 产生 229。有人可以帮助澄清为什么会发生这种情况以及如何解决它以获得预期结果d1 230?
数字 2.3 无法用 IEEE-754 二进制 64(“双精度”)类型表示。源代码
2.3000
转换为最接近的可表示值,即2.29999999999999982236431605997495353221893310546875。 (下一个更高的可表示值是 2.300000000000000266453525910037569701671600341796875,距离 2.3 更远。)
将其转换为
decimal
类型会产生一个约 2.2999999999999999822364316 的数字…将其乘以 100 会产生约 229.9999999999999822364316 的值…将其转换为 int
会截断,产生 229。
…我相信此类错误发生在较低的有效位上,而不是代表较高数字的高位…
对较低位的影响会传递到较高位。从 230 减去任何正数都会得到小于 230 的数字,无论减去的金额有多小。