为什么Math.Round(2.5)返回2而不是3?

在C#中, Math.Round(2.5)的结果是2。

它应该是3,不是吗? 为什么它是2而不是C#?


首先,这不会是一个C#错误 - 这将是一个.NET错误。 C#是语言 - 它并不决定Math.Round是如何实现的。

其次,不 - 如果你阅读文档,你会发现默认的四舍五入是“圆到平”(银行家的四舍五入):

返回值
类型:System.Double
最接近的整数。 如果a的小数部分在两个整数之间,其中一个是偶数,另一个是奇数,则返回偶数。 请注意,此方法返回Double而不是整型。

备注
这种方法的行为遵循IEEE标准754第4部分。这种舍入有时被称为舍入到最近或银行家舍入。 它最大限度地减少了在一个方向上始终舍入中点值所导致的舍入误差。

您可以指定Math.Round应如何使用采用MidpointRounding值的重载对MidpointRounding进行舍入。 有一个重载与一个MidpointRounding相对应,每个重载没有一个:

  • Round(Decimal) / Round(Decimal, MidpointRounding)
  • Round(Double) / Round(Double, MidpointRounding)
  • Round(Decimal, Int32) / Round(Decimal, Int32, MidpointRounding)
  • Round(Double, Int32) / Round(Double, Int32, MidpointRounding)
  • 这种违约是否被恰当地选择是另一回事。 ( MidpointRounding仅在.NET 2.0中引入,在此之前我不确定是否有任何简单的方法来实现所需的行为,而无需亲自执行。)特别是,历史记录显示它不是预期的行为 - 并且在大多数情况下这是API设计中的一个主要罪过。 我明白为什么银行家的舍入是有用的......但对许多人来说,这仍然是一个惊喜。

    您可能有兴趣查看最近的Java等价枚举( RoundingMode ),它提供了更多的选项。 (它不只是处理中点。)


    这就是所谓的四舍五入甚至(或银行家的四舍五入),这是一种有效的四舍五入策略,用于最大限度地减少总和中的累积误差(MidpointRounding.ToEven) 。 理论是,如果你总是在同一个方向上舍入一个0.5的数字,那么错误会更快地产生(圆到平均应该最小化)(a)。

    请按以下链接查看以下MSDN描述:

  • Math.Floor ,向着无穷大的方向发展。
  • Math.Ceiling ,正向无穷大迈进。
  • Math.Truncate ,向上Math.Truncate或向下Math.Truncate为零。
  • Math.Round ,将四舍五入到最接近的整数或指定的小数位数。 您可以指定行为,如果它在两种可能性之间完全等距,例如舍入,以便最后一位数字为偶数(“ Round(2.5,MidpointRounding.ToEven) ”变为2)或远离零(“ Round(2.5,MidpointRounding.AwayFromZero) “成为3)。
  • 下图和表格可能有所帮助:

    -3        -2        -1         0         1         2         3
     +--|------+---------+----|----+--|------+----|----+-------|-+
        a                     b       c           d            e
    
                           a=-2.7  b=-0.5  c=0.3  d=1.5  e=2.8
                           ======  ======  =====  =====  =====
    Floor                    -3      -1      0      1      2
    Ceiling                  -2       0      1      2      3
    Truncate                 -2       0      0      1      2
    Round(ToEven)            -3       0      0      2      3
    Round(AwayFromZero)      -3      -1      0      2      3
    

    请注意, Round比看起来更强大,因为它可以舍入到特定的小数位数。 所有其他人总是舍入零小数。 例如:

    n = 3.145;
    a = System.Math.Round (n, 2, MidpointRounding.ToEven);       // 3.14
    b = System.Math.Round (n, 2, MidpointRounding.AwayFromZero); // 3.15
    

    与其他功能,你必须使用乘法/除法欺骗来达到相同的效果:

    c = System.Math.Truncate (n * 100) / 100;                    // 3.14
    d = System.Math.Ceiling (n * 100) / 100;                     // 3.15
    

    (a)当然,这个理论取决于这样一个事实,即你的数据在偶数平均数(0.5,2.5,4.5,...)和奇数平均数(1.5,3.5,...)之间具有相当均匀的价值分布。

    如果所有的“半值”都是evens(例如),那么这些错误的累积速度就像你总是四舍五入一样快。


    从MSDN,Math.Round(double a)返回:

    最接近的整数。 如果a的小数部分在两个整数之间,其中一个是偶数,另一个是奇数,则返回偶数。

    ...等2.5,在2和3之间的中间,被舍入到偶数(2)。 这被称为银行家舍入(round-to-even),是一个常用的舍入标准。

    同样的MSDN文章:

    这种方法的行为遵循IEEE标准754第4部分。这种舍入有时被称为舍入到最近或银行家舍入。 它最大限度地减少了在一个方向上始终舍入中点值所导致的舍入误差。

    您可以通过调用采用MidpointRounding模式的Math.Round重载来指定不同的舍入行为。

    链接地址: http://www.djcxy.com/p/48413.html

    上一篇: Why does Math.Round(2.5) return 2 instead of 3?

    下一篇: In .net, how do I choose between a Decimal and a Double