C#银行家的舍入错误

时间:2010-09-23 06:07:03

标签: c# rounding bankers-rounding

double a = 18.565
return Math.Round(a,2)

..返回18.57 对于其他所有数字,我尝试过银行家的舍入按预期工作,例如Math.Round(2.565,2)返回2.56。

任何线索为什么以及何时发生? 这是错误还是我错过了关于银行家四舍五入的事情?

谢谢..

4 个答案:

答案 0 :(得分:16)

马修说,18.565无法准确表达。使用的实际值是18.565000000000001278976924368180334568023681640625(使用DoubleConverter找到),这显然超出了一半。现在我有一种偷偷摸摸的感觉,有时 Math.Round会考虑一个实际超出中途点的值,但是接近一半可以准确地表示的路点,正好是 at 那一点。但是,我没有看到任何描述应用情况的文档,显然在这种情况下并没有发生。我不想依赖它。

当然,即使是舍入值也不是18.57。它实际上是18.57000000000000028421709430404007434844970703125。

从根本上说,如果您真的非常关心准确表示小数值,那么您应该使用decimal。这不仅仅是Math.Round - 它涉及处理浮点值的每个方面。

确实Math.Round提供正确的价值,当然:

decimal m = 18.565m;
Console.WriteLine(Math.Round(m, 2)); // Prints 18.56

答案 1 :(得分:5)

18.565无法准确表示为双精度数。因此,二进制表示略高,因此它向上舍入。如果你使用十进制:

decimal a = 18.565m;
return Math.Round(a,2)

它可以准确表示,你不会遇到这个问题。

答案 2 :(得分:1)

我的猜测是FP表示意味着它实际上不是尾随5; FP的危险!

但这很好,但是:

        decimal a = 18.565M; // <===== decimal
        var s = Math.Round(a, 2);

答案 3 :(得分:0)

Double是浮点值,所以如果你把它写成18.565,它实际上在内存中就像是18.565000000000000000000000000000000000001,因此它超过了中点。