为什么.NET使用银行家的舍入作为默认值?

Why does .NET use banker's rounding as default?

根据文献的方法,使用一个decimal.Round全面均衡算法的最普通的应用是困难的。所以我总是最终编写自定义函数做了更多的自然循环式算法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public static decimal RoundHalfUp(this decimal d, int decimals)
{
    if (decimals < 0)
    {
        throw new ArgumentException("The decimals must be non-negative",
           "decimals");
    }

    decimal multiplier = (decimal)Math.Pow(10, decimals);
    decimal number = d * multiplier;

    if (decimal.Truncate(number) < number)
    {
        number += 0.5m;
    }
    return decimal.Round(number) / multiplier;
}

没有人知道原因在本框架的设计决策?

有没有任何内置的全面实施半升到框架的算法?或也许一些非托管的Windows API?

对于成本,它可以是简单的初学者写的decimal.Round(2.5m, 0)as a result,但希望获得3而不是2。


另一个答案是,为什么银行家的算法(也就是半圆形到偶数圆形)是一个很好的选择,这是非常正确的。在最合理的分布情况下,它不受负偏压或正偏压的影响。

但问题是,为什么.NET使用Banker的实际舍入作为默认值——答案是微软已经遵循了IEEE754标准。这也在msdn for math.round的备注中提到。

还请注意,.NET通过提供MidpointRounding枚举支持IEEE指定的替代方法。当然,他们可以为解决关系提供更多的选择,但他们选择只满足IEEE标准。


可能是因为它是一个更好的算法。在执行的许多舍入过程中,您将平均得出所有.5的最终舍入相等。这可以更好地估计实际结果,例如,添加一组四舍五入的数字。我会说,尽管这不是一些人所期望的,但这可能是更正确的做法。


虽然我不能回答"为什么微软的设计师选择这个作为默认值?",我只是想指出一个额外的函数是不必要的。

Math.Round允许您指定MidpointRounding

  • 当一个数介于两个数之间时,它会四舍五入到最接近的偶数。
  • A从零开始-当一个数字介于两个数字之间时,它会四舍五入到离零最近的数字。


小数主要用于货币;银行家在处理货币时通常使用四舍五入。或者你可以说。

It is mostly bankers that need the
decimal type; therefore it does
"banker’s rounding"

银行家四舍五入的优点是,如果您:

  • 将一组"发票行"舍入,然后再将它们相加,
  • 或者把它们加起来,然后把总数四舍五入

加起来之前的四舍五入节省了计算机前几天的大量工作。

(在我们去英国的时候,十进制的银行不会处理半便士的问题,但多年来,仍有半便士的硬币,商店的价格通常以半便士结束——所以有很多四舍五入法)


使用类似以下的另一个循环函数重载:

1
decimal.Round(2.5m, 0,MidpointRounding.AwayFromZero)

它将输出3。如果你使用

1
decimal.Round(2.5m, 0,MidpointRounding.ToEven)

你会得到银行的四舍五入。