处理货币密集型软件四舍五入错误的常用策略?

时间:2010-05-18 19:30:08

标签: algorithm numbers rounding finance

您对此有何建议:

  1. 补偿在Money对象集合上的批量数学运算中累积的错误。如何在您的语言环境的生产代码中实现这一点?
  2. 会计四舍五入后的
  3. 理论
  4. 关于主题的任何文献
  5. 我目前正在阅读Fowler。他提到了Money类型,它是典型结构(int,long,BigDecimal),但没有说明策略。

    关于赚钱的旧帖子(herehere)不提供我需要的详细信息和形式。

    我在inet中发现的想法与“Round half even”相关,是平衡错误的最佳方法。

    感谢您的帮助。

6 个答案:

答案 0 :(得分:5)

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

  • 大多数数据库都提供十进制数据类型,您可以在其上指定小数点前后的位数(货币也以十进制数字的数字变化,我已经处理了0,2,3个十进制数字的货币)< / LI>
  • 在处理这些数据时,你想避免在应用程序端出现任何意外的舍入错误,你可以使用BCD作为通用方法,或者你可以使用整数表示任何固定的十进制表示法或混合你自己的

如果第一个问题被整理出来,那么任何添加(或减法)都不会引入任何舍入错误。乘以整数也是一样。

第二个问题是,在能够存储和检索数据而不丢失信息之后,预计会因为除法而导致舍入错误(或乘以非整数)。

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

10.00  
-3.33  
-3.33  
-3.33  

-0.01 

(舍入错误)

这是预期的问题,无论数据类型存储选择如何,如果您希望帐户平衡,都需要注意这一问题。这种情况主要是通过除法(或通过乘以具有许多有效数字的非整数)引入的。

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

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

答案 1 :(得分:4)

永远不要将货币值存储在double或float中 - 使用intlong,因为无法以二进制形式准确存储0.1。

答案 2 :(得分:3)

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

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

您可以对此进行扩展以将toward舍入到最近的两便士。所以22.5轮到22轮,但是23.5轮到24. 23.1轮和22.9轮都是23轮。然而,原来的银行家的算法更受欢迎。

答案 3 :(得分:3)

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

对于需要舍入的情况,只要您选择一个策略,进行沟通并坚持下去,您所做的事情并不重要。例如,我相信我的储蓄账户的利息会减少到最近的一分钱。

答案 4 :(得分:1)

我的工作量(只是一点点)有金额,我对我公司使用的策略非常好奇......

事实证明我们使用double,但他们已经考虑过了。

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

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

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

  • 从一个钱转换到另一个钱,当然不断改变
  • 打印问题,一些资金不需要小数,其他资金最多需要2,等等......

也许您可以扩展您正在进行的操作吗?

答案 5 :(得分:1)

您应该做的事情可能会被您所经营的市场或司法管辖区的惯例所告知。例如,澳大利亚市场的定价债券要求您将某些中间操作舍入到小数点后8位。最终价格被引用到特定的小数位数(3我认为不在我的头顶)。

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