根据文档,小数。圆整法使用的是一种圆整到偶数的算法,这在大多数应用中并不常见。所以我总是写一个自定义函数来实现更自然的四舍五入算法:

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,这可能会产生误导。


当前回答

使用另一个重载Round函数,如下所示:

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

它将输出3。如果你用

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

你会得到银行四舍五入。

其他回答

使用另一个重载Round函数,如下所示:

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

它将输出3。如果你用

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

你会得到银行四舍五入。

其他的答案解释了为什么银行家的算法(即二分之一到偶数)是一个很好的选择,这是非常正确的。在大多数合理的分布上,它不会受到负或正偏差的影响。

但是问题是。net为什么使用Banker的实际舍入作为默认值——答案是微软已经遵循了IEEE 754标准。数学的MSDN中也提到了这一点。在备注下四舍五入。

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

小数主要用于表示货币;银行家四舍五入在与金钱打交道时很常见。或者你可以说。

需要资金的主要是银行家 十进制类型;因此确实如此 “银行家的舍入”

银行家舍入的优势是,平均而言,如果你:

把一组“发票行”四舍五入,然后再加起来, 或者把它们加起来,然后四舍五入

在没有计算机的时代,先四舍五入再加可以节省很多工作。

(在英国,十进位银行不处理半便士,但多年来仍然有半便士硬币,商店的价格经常以半便士结尾,所以有很多四舍五入)

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

数学。Round允许你指定一个midpointrsurround:

至偶数——当一个数字位于另外两个数字的中间时,将它四舍五入到最接近的偶数。 awayfrom0 -当一个数字位于另外两个数字的中间时,它会四舍五入到距离0最近的数字。

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