BigDecimal和Money

7
我进行了研究并发现,在处理货币时,使用 BigDecimal 类进行计算是最佳方法。
考虑到这一点,我正在编写一个代码,将各种类型的外币转换为美元,反之亦然(具体来说,是一个现金注册机,它接受外币并将其转换为美元,计算找零金额并以外币形式返回给客户)。
目前,许多方法使用 double ,其中两个方法使用 int 作为参数用于计算美元。
问题:
既然我想在计算中使用BigDecimal类,那么是否应将所有涉及double的计算方法更改为BigDecimal?

2
是的,这听起来是个好主意。赞成避免在此使用浮点数。 - Hovercraft Full Of Eels
另一种计算货币的实用方法是使用有理数。它们具有“无限”的精度,稳定性也比BigDecimal更快。 - Neet
2个回答

4

是的,你应该将所有浮点数或双精度数更改为使用整数、长整数或BigDecimals

对于财务计算,浮点数和双精度数不够精确。使用Money模式来处理金额和货币是一个非常好的想法(它是一种特殊类型的Quantity)。为了维护可能存在多种货币的资金列表,你实际上正在做一个MoneyBag,这是一个包含多个Money的集合,可以在给定目标货币和CurrencyExchangeService(货币转换率也应存储为BigDecimals)的情况下对所有值进行求和。

根据所需小数位数和舍入算法,在每次操作后应进行四舍五入。小数位数通常是Currency的属性(例如,请参见ISO 4217),除非需要不同的数字(例如,当定价汽油时)。

你应该确实查看Fowler的示例;但我也创建了一个非常简单的单货币Money类,用于练习。它仅使用美元并四舍五入到2位小数,但仍然是未来扩展的良好基础。


有时候金融计算需要采用更复杂的方法。例如,一个典型的情况是将一个金额分成n%和(100-n)%两部分,以便这些部分的总和完全符合精确到分的要求,尽管存在四舍五入。 - 9000
@9000:是的,Fowler为此描述了一种分配算法,请看PoEAA;我之前也曾经使用过,并且获得了巨大的成功。 - Jordão
那是Jordao和9000,我想我需要使用BigDecimal。 - Wormhole99
@Wormhole99:所以,你有多种货币,但仍然不会创建一个“Money”类吗?你应该_强烈_考虑一下。这种抽象将使你的程序更易于理解和维护。 - Jordão
好的,我会研究一下。感谢您发布那个算法。 - Wormhole99

1

是的,BigDecimal肯定是正确的方式(浮点数几乎从不使用)。在JDBC中也是如此。

但话虽如此,舍入存在问题。在某些情况下,欧洲软件法律上要求6位小数。通常情况下,您会希望在每个步骤中保留2位小数进行四舍五入。如果您有一个带有2个小数和价格的数量,则会得到4个小数,并且必须进行舍入。因此,为了使丑陋的BigDecimal接口更加丑陋,您可能需要一些辅助函数(multiplyRounded?)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接