代码之家  ›  专栏  ›  技术社区  ›  Darin Dimitrov

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

  •  255
  • Darin Dimitrov  · 技术社区  · 17 年前

    decimal.Round 该方法使用一种从圆到平的算法,这在大多数应用程序中并不常见。因此,我总是编写一个自定义函数来执行更自然的取整半向上算法:

    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) 预期结果为3,但得到2。

    5 回复  |  直到 15 年前
        1
  •  444
  •   Ostemar    5 年前

    另一个答案是为什么银行家算法(又名 round half to even )这是一个很好的选择,你的回答很正确。它不像其他人那样受到消极或积极偏见的影响 round half away from zero 最合理分布上的方法。

    IEEE 754 标准这一点也在本文中提到 MSDN for Math.Round 根据评论。

    还请注意,.NET通过提供 MidpointRounding 枚举。他们当然可以提供 more alternatives

        2
  •  203
  •   Kibbee    17 年前

    可能是因为这是一个更好的算法。在进行多次舍入的过程中,你将平均得出所有.5的结果都是上下平均舍入。这可以更好地估计实际结果,例如,添加一组四舍五入的数字。我想说,尽管这不是一些人所期望的,但这可能是更正确的做法。

        3
  •  88
  •   casperOne    15 年前

    虽然我无法回答“为什么微软的设计师选择这个作为默认设置?”的问题,但我只想指出,没有必要使用额外的功能。

    Math.Round 允许您指定 MidpointRounding :

    • ToEven-当一个数字介于其他两个数字之间时,它将向最近的偶数舍入。
    • 远离零-当一个数字位于其他两个数字的中间时,它将向远离零的最近数字四舍五入。
        4
  •  22
  •   Ian Ringrose    15 年前

    小数主要用于数字 钱 ; 在使用时,四舍五入是常见的

    大多数银行家需要这一点 十进制类型;因此它确实如此 银行家四舍五入

    银行家的优势在于,如果您:

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

    (在英国,当我们使用十进制时,银行不会处理半便士的硬币,但多年来仍然有半便士的硬币,商店的价格通常以半便士结尾,所以有很多舍入)

        5
  •  0
  •   Omid Sadeghi    9 年前

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

    它将输出 . 如果你使用

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

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

    推荐文章