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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/311696/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 10:40:20  来源:igfitidea点击:

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

.netrounding

提问by Darin Dimitrov

According to the documentation, the decimal.Roundmethod uses a round-to-even algorithm which is not common for most applications. So I always end up writing a custom function to do the more natural round-half-up algorithm:

根据文档,该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;
}

Does anybody know the reason behind this framework design decision?

有人知道这个框架设计决策背后的原因吗?

Is there any built-in implementation of the round-half-up algorithm into the framework? Or maybe some unmanaged Windows API?

框架中是否有四舍五入算法的内置实现?或者也许是一些非托管的 Windows API?

It could be misleading for beginners that simply write decimal.Round(2.5m, 0)expecting 3 as a result but getting 2 instead.

对于仅仅写decimal.Round(2.5m, 0)期望 3 结果却得到 2 的初学者来说,这可能会产生误导。

采纳答案by Kibbee

Probably because it's a better algorithm. Over the course of many roundings performed, you will average out that all .5's end up rounding equally up and down. This gives better estimations of actual results if you are for instance, adding a bunch of rounded numbers. I would say that even though it isn't what some may expect, it's probably the more correct thing to do.

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

回答by Ostemar

The other answers with reasons why the Banker's algorithm (aka round half to even) is a good choice are quite correct. It does not suffer from negative or positive bias as much as the round half away from zeromethod over most reasonable distributions.

银行家算法(又名round half to even)是一个不错的选择的原因的其他答案是非常正确的。在大多数合理分布中,它不会像远离零圆形一半方法那样受到负或正偏差的影响。

But the question was why .NET use Banker's actual rounding as default - and the answer is that Microsoft has followed the IEEE 754standard. This is also mentioned in MSDN for Math.Roundunder Remarks.

但问题是为什么 .NET 使用 Banker 的实际舍入作为默认值 - 答案是 Microsoft 遵循了IEEE 754标准。MSDN for Math.Round 的备注下也提到了这一点。

Also note that .NET supports the alternative method specified by IEEE by providing the MidpointRoundingenumeration. They could of course have provided more alternativesto solving ties, but they choose to just fulfill the IEEE standard.

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

回答by Michael Stum

While I cannot answer the question of "Why did Microsoft's designers choose this as the default?", I just want to point out that an extra function is unnecessary.

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

Math.Roundallows you to specify a MidpointRounding:

Math.Round允许您指定一个MidpointRounding

  • ToEven - When a number is halfway between two others, it is rounded toward the nearest even number.
  • AwayFromZero - When a number is halfway between two others, it is rounded toward the nearest number that is away from zero.
  • ToEven - 当一个数字介于其他两个数字之间时,它会向最接近的偶数四舍五入。
  • AwayFromZero - 当一个数字在其他两个数字的中间时,它会向离零最近的数字四舍五入。

回答by Ian Ringrose

Decimals are mostly used for money; banker's rounding is common when working with money. Or you could say.

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

It is mostly bankers that need the decimal type; therefore it does “banker's rounding”

需要十进制类型的主要是银行家;因此它做了“银行家的四舍五入”

Bankers rounding have the advantage that on average you will get the same result if you:

银行家四舍五入的优势在于,如果您:

  • round a set of “invoice lines” before adding them up,
  • or add them up then round the total
  • 在将一组“发票行”加起来之前将它们围起来,
  • 或者把它们加起来然后四舍五入

Rounding before adding up saved a lot of work in the days before computers.

在计算机出现之前的日子里,在加起来之前进行四舍五入节省了大量工作。

(In the UK when we went decimal banks would not deal with half pence, but for many years there was still a half pence coin and shop often had prices ending in half pence – so lots of rounding)

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

回答by Omid Sadeghi

Use another overload of Round function like this:

像这样使用 Round 函数的另一个重载:

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

It will output 3. And if you use

它将输出3。如果你使用

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

you will get banker's rounding.

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