当前位置:  开发笔记 > 数据库 > 正文

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

如何解决《为什么.NET使用银行家的舍入作为默认值?》经验,为你挑选了4个好方法。

根据文档,该decimal.Round方法使用round-to-even算法,这对于大多数应用程序来说并不常见.所以我总是最终编写一个自定义函数来做更自然的圆半算法:

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.



1> Ostemar..:

另一个答案是为什么银行家的算法(也就是一半到一半)是一个不错的选择是非常正确的.与大多数合理分布相比,它没有像零方法那样的圆半部分遭受负偏差或正偏差.

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

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


那么,为什么IEEE 754会跟随银行家四舍五入呢?这个(仍然很好)的答案刚刚过去了.
@HenkHolterman可能是由于其他答案中提到的内容(以及我总结的); 它不会受到负面或正面偏见的影响(过多),因此对大多数发行版和问题域都会产生更合理的默认值.

2> Kibbee..:

可能是因为它是一个更好的算法.在执行多次舍入的过程中,您将平均所有.5的最终向上和向下舍入.如果您是例如添加一堆舍入数字,则可以更好地估计实际结果.我会说即使它不是人们所期望的,但这可能是更正确的事情.


假设你当然有奇数和偶数输入的平坦分布
为*更好的算法*+1,虽然Ostemar有*实际*答案(http://stackoverflow.com/questions/311696/why-does-net-use-bankers-rounding-as-default/6562018#6562018)
@Ian,我也给出了答案+1.无论如何,我们可以得到"已接受的答案",也许OP可以做到这一点.它为什么使用这种方法的实际答案是在页面的一半.虽然我非常喜欢这种代表性的提升,但每周我会从这个答案中得到一次.

3> Michael Stum..:

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

Math.Round允许您指定MidpointRounding:

ToEven - 当一个数字介于另外两个数字之间时,它会向最接近的偶数舍入.

AwayFromZero - 当一个数字介于另外两个数字之间时,它会向最接近零的数字四舍五入.


一位客户曾向我支付了超过40,000美元,以追查两个数字之间的0.11美元舍入错误,这两个数字都差不多十亿美元; $ 0.11是由于大型机和SQL Server之间的第8位舍入误差的差异.谈论一个完美主义者!
@EJ Brennan:你花了4万美元来解决这个问题?我总是看到这样的问题,舍入是因为#1,双/浮点归一化是因为#2,程序员错误#3 - 如果没有预定义的测试用例,#3可以立即设置为#1.顺便问一下,请你让我与你的亿万客户联系,我想我可以在他的系统中找到更多4万美元的漏洞!:d
@EJB - 如果我处理十亿美元,我可能会成为一个完美主义者;-)
正如我在相关主题中所提到的,确保你在舍入中保持一致 - 如果你有时在数据库中进行四舍五入,有时在.net中,你会有奇怪的,一分钱的错误需要几周时间才能完成弄清楚.
@seanxe:或者你看过Office Space.说真的,每当你看到金钱的神秘,微小的不准确,解决它们究竟是如何发生的奥秘几乎总是一个好主意.您可能决定不修复错误,但了解根本原因仍然有价值.我敢打赌,许多从事金钱工作的人都很高兴地注意到甚至很小的不准确之处.
"为什么微软的设计师会选择这个作为默认设置?" 他们没有; IEEE做到了.请参阅Ostemar的回答:http://stackoverflow.com/a/6562018/385844(对不起讽刺措辞,但如果我遇到的每个开发人员认为"微软在他们的舍入程序中存在错)

4> Ian Ringrose..:

小数几乎用于赚钱 ; 在与合作时,银行家的四舍五入很常见.或者你可以说.

大多数银行家都需要十进制类型; 因此,它"银行家的四舍五入"

银行家四舍五入的优势在于,如果您:平均获得相同的结果:

在添加它们之前围绕一组"发票行",

或者将它们加起来然后围绕总数

加起来之前的舍入在计算机之前的日子里节省了大量的工作.

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


"十进制主要用于赚钱"......以及其他不是整数的东西.
@JohnTyree,大多数情况下,当它不是整数时,使用double/float是不正确的.见http://stackoverflow.com/questions/2545567/in-net-how-do-i-choose-between-a-decimal-and-a-double
哇.我这个荒谬的错误.`Decmial`s,是的.小数,没有.对于后代,我同意这里的原始观点.
推荐阅读
mobiledu2402852413
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有