用 integers/BigInteger 与 BigDecimal 表示金钱

Representing money with integers/BigInteger vs BigDecimal

几年前,我帮助编写了一个处理金钱和保险的应用程序。最初,我们用浮点数表示货币(我知道这是一个很大的禁忌)。大多数应用程序只是添加和减去值,因此没有任何问题。但是,特定部分涉及货币价值的百分比,因此涉及乘法和除法。

我们立即开始遭受浮点错误的困扰,不得不进行重大重构。我们使用了一个任意精度的库来解决这个问题。但是,这并没有改变您最终只能得到几分之一美分的事实。你应该如何舍入?简短的回答是“it's complicated”。

现在我正准备着手开发一个类似的应用程序来取代旧的应用程序。多年来我一直在考虑这个问题。我一直认为最简单的方法是创建一个包含整数(或 BigInteger)的货币数据类型来表示便士的数量,并具有将其打印为传统的、人性化的 [=12=].00 格式的功能。

然而,研究这个,我发现 JSR 354,最近实施的 Java 金钱 API。我惊讶地发现它用 BigDecimal 来支持它的货币表示。因此,它包含特定的舍入逻辑。

在您的计算中携带几分之一美分有什么好处?为什么我要这样做而不是说一分钱是 "atomic" 形式的钱?

这是一个宽泛的问题,因为它的答案因实施而异。

如果我以 5 美元的价格批量购买 1000 件商品,那么每件商品的单价为 0.005 美元,低于您声称的 "atomic form" 金额 0.01 美元。

如果我们将 0.01 美元视为可能的最低金额,那么我们将无法处理特定情况下的计算,例如我的示例中的情况。

出于这个原因,JavaMoney API 处理许多小数位,确保在这种情况下不会丢失精度。