C#银行家的舍入错误

Dam*_*mir 8 c# bankers-rounding rounding

double a = 18.565
return Math.Round(a,2)
Run Code Online (Sandbox Code Playgroud)

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

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

谢谢..

Jon*_*eet 16

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

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

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

当然,这确实给了正确的价值Math.Round:

decimal m = 18.565m;
Console.WriteLine(Math.Round(m, 2)); // Prints 18.56
Run Code Online (Sandbox Code Playgroud)


Mat*_*hen 5

18.565不能完全表示为double.因此,二进制表示略高,因此它向上舍入.如果使用小数:

decimal a = 18.565m;
return Math.Round(a,2)
Run Code Online (Sandbox Code Playgroud)

它可以准确表示,你不会有这个问题.