【发布时间】:2019-04-11 22:55:16
【问题描述】:
以下 C# 代码:
int n = 3;
double dbl = 1d / n;
decimal dec = 1m / n;
Console.WriteLine(dbl * n == 1d);
Console.WriteLine(dec * n == 1m);
输出
True
False
显然,double 和 decimal 都不能准确地表示 1/3。但是dbl * n 舍入为 1 而dec * n 不是。为什么?这种行为记录在哪里?
更新
请注意,我的主要问题是为什么它们的行为不同。假设舍入的选择是设计 IEEE 754 和 .NET 时有意识的选择,我想知道选择一种舍入而不是另一种的原因是什么。在上面的示例中,double 似乎在生成数学上正确的答案时表现更好,尽管有效数字少于decimal。为什么decimal 的创建者不使用相同的舍入?是否存在decimal 的现有行为会更有益的情况?
【问题讨论】:
-
double => IEEE 754 ... 十进制明显 => 假设十进制有 N 精度 1/3 = 0.333333... 最多 N 位 .. 所以 0.3333 ... * 3 是 0.9999 ....仍然最多 N 个地方
-
Console.WriteLine行之前,dec的值是多少。这回答了问题的dec方面。对于问题的dbl方面-您在寻找什么文档?这与您对浮点数学的理解有何不一致? 请注意,dbl的行为肯定不是保证 - 它在不同的 CPU 和运行时可能会以不同的方式工作。 -
@Sinatr:
decimal不会“自我恢复”,这就是重点。0.33....3 * 3 == 0.99...9。结果可以准确表示。double不会发生这种情况,因为相乘后的分数比最终结果具有更多(二进制)数字,并且四舍五入使事情回到1。没有(整数)n会导致与decimal相同的结果,但可以通过使用0.3的decimal n来实现相同的效果。 -
@JeroenMostert,正如您所说,十进制似乎与 double 表现不同的原因不是它们使用不同类型的舍入,而是没有溢出来触发舍入。结果以十进制精确表示(0.33....3 * 3 == 0.99...9),而对于 double 则不是。我认为这回答了我的问题。