【问题标题】:Common strategies to deal with rounding errors in currency-intensive soft?货币密集型软中处理舍入误差的常用策略?
【发布时间】:2010-05-18 19:30:07
【问题描述】:

你有什么建议:

  1. 补偿对 Money 对象集合的批量数学运算中的累积错误。这是如何在您所在地区的生产代码中实现的?
  2. 会计四舍五入背后的理论
  3. 任何关于主题的文献

我目前正在阅读Fowler。他提到了 Money 类型,它是典型的结构(int、long、BigDecimal),但没有提及策略。

关于四舍五入的旧帖子(herehere)没有提供我需要的细节和形式。

我在 inet 中发现的想法与“四舍五入”有关,这是平衡错误的最佳方法。

感谢您的帮助。

【问题讨论】:

  • 如果你问的是会计,你应该问一个真正的会计师。他们有规则。在美国,涵盖这一点的是 GAAP。你问过会计吗?您是否找到适用于您所在地区的会计规则?
  • @S.Lott:嗨,我在立陶宛。今天我和当地的银行工作人员谈过:)。她说我在月底或季度末他们只是注销了差异。但是这个答案不符合我的需要。
  • 那就找个更好的会计师吧。严重地。这很可能在立陶宛的法律中有所涵盖。如果不是根据法律,那么根据某些专业标准(这就是美国的公认会计原则)。会计师对此有充分的记录。
  • @S.Lott:谢谢,S。我找到了一些关于问题的文章,这似乎与您提到的当地标准有关。我对鳍体接受的技术差异感到惊讶。如果您也有兴趣,可以使用“软件国际化”浏览主题...

标签: algorithm numbers rounding finance


【解决方案1】:

记录财务数据时存在许多舍入问题。 第一个问题是存储和检索精确十进制数字的能力

  • 大多数数据库都提供十进制数据类型,您可以在该数据类型上指定小数点前后的位数(货币的小数位数也不同,我处理的货币有 0、2、3 位小数)
  • 在处理这些数据时,如果您希望避免应用程序端出现任何意外的舍入错误,您可以使用 BCD 作为通用方法,或者您可以使用整数来表示任何固定的十进制表示法或混合使用自己的方法

如果解决了第一个问题,则任何加法(或减法)都不会引入任何舍入错误。乘以整数也是如此。

第二个问题,在您能够在不丢失信息的情况下存储和检索数据之后,预计会由于除法(或非整数相乘)导致舍入错误。

例如,如果您的货币格式允许 2 位小数,并且您想要存储记录余额为 10 到 3 个等额借方的交易,您只能将其存储为

10.00  
-3.33  
-3.33  
-3.33  

-0.01 

(舍入误差)

无论选择何种数据类型存储,都会出现此问题,如果您希望帐户保持平衡,则需要注意这一问题。这种情况主要是由除法(或乘以具有许多有效数字的非整数)引起的。

解决此问题的一种方法是验证您的数据在此类操作后是否平衡,并识别允许的舍入差异而不是错误情况。

编辑: 至于参考文献,this one 似乎很有趣,而且不会太长,并且涉及相当广泛的受众和有趣的场景。

【讨论】:

  • 谢谢你提醒我 BCD 的东西。是的,我确信持久性是可以的,并且允许精确的小数。一般来说,我的问题可以提炼到关于总结小额金额的观点。遗憾的是我并没有完全控制我自己总结的这种故障:)。所以我可能不得不求助于 Round half 甚至 Gaussian 方法或任何其他统计方法......
  • @Max,处理这些累积舍入错误的策略取决于您的业务规则(有时您需要使金额相等并且您必须记录错误,其他时候允许分发舍入误差)。
  • 与 BA 交谈,我们将对我们的部分进行更改,并要求更改为我们提供这些“小的不精确”细分数量的外部系统。无论如何,这篇 SO 帖子很有价值——至少我开始觉得四舍五入的员工比我想象的更有趣:)
【解决方案2】:

使用银行家的四舍五入。你四舍五入到最接近的两便士。

http://www.xbeat.net/vbspeed/i_BankersRounding.htm

您可以在此基础上将toward 舍入到最接近的两便士。所以 22.5 轮到 22,但是 23.5 轮到 24。23.1 和 22.9 都轮到 23。但是,原始的银行家算法更受欢迎。

【讨论】:

    【解决方案3】:

    永远不要以双精度或浮点数存储货币值 - 使用 intlong,因为无法以二进制形式准确存储 0.1。

    【讨论】:

    • 通常那些 int's & long's & BigDecimal's 是 Money 的内部结构。有趣的是,当您对 Money 执行大量操作时,如何应对累积错误。
    • @max:这是什么,会计溢出? ;)
    • 你在做什么操作?标准算术运算不会有任何舍入误差——这就是使用定点表示的目的。
    【解决方案4】:

    这完全取决于应用程序。希望没有太多需要四舍五入的情况。例如,将资金从一个帐户转移到另一个帐户不需要四舍五入。

    对于需要四舍五入的情况,只要您选择政策、传达政策并坚持下去,您做什么并不重要。例如,我相信我的储蓄账户上的利息会四舍五入到最接近的一美分。

    【讨论】:

      【解决方案5】:

      您应该做的事情可能会根据您所在的市场或司法管辖区的惯例来确定。例如,澳大利亚市场的债券定价要求您将某些中间操作四舍五入到小数点后 8 位。最终价格以特定的小数位数报价(我想不到 3)。

      如果您正在处理会计应用程序,我希望您的法律环境的相关会计标准可能会规定这一点。

      【讨论】:

        【解决方案6】:

        我在货币金额方面做了一些(只是一点点)工作,我对我公司使用的策略非常好奇......

        原来我们使用double,但他们已经考虑过了。

        问题是我们处理的金额不是很大(比如少于 10k),我们最多需要小数点后 3 位,总共 7 位有效数字。

        由于我们使用的是 64 位软件(和 C++),double 类型为我们进行的操作数量提供了足够的有效数字 :)

        如果您需要更高的精度,可以使用一些算法(例如在添加多笔资金时),但我个人认为问题的核心更多来自:

        • 从一种货币转换为另一种货币,当然会不断变化
        • 打印问题,有些钱不需要小数,有些最多需要 2,等等...

        也许你可以扩展你正在做的操作?

        【讨论】:

        • 嗨,马修。我还看到一个遗留系统在双打上工作......我们面临着几个问题(你提到的货币转换也是如此)。其他类似于 www.ciceuta.es/euro/doc/1/eup22en.pdf 中提到的。典型的是通过除法和乘法获得的小数的总和存在差异。似乎,我将提高这些中间操作的精度,并可能重建计算(但是部分“小数字”数据不受我控制)。我得出的结论是,要么我们忽略错误,要么通过平衡四舍五入来补偿,如 Round-half-even。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-09-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多