Java快速货币表示法?

4

我正在开发一个实时应用程序,处理不同货币和汇率的资金,使用BigDecimal,但我遇到了一些严重的性能问题,我想改变底层表示。

我一遍又一遍地阅读,发现在Java中表示资金的一种好而快速的方法是使用长整型存储分(或所需精度),如评论中指出的那样,有一些包装器库可以做到这一点,例如JavaMoney中的FastMoney。

这里有两个问题。

  1. 将钱存储为长整型(或在包装器内部)并将其他所有内容(如汇率)保留为double,这样做是否始终安全?换句话说,如果我执行Math.round(money * rate)(money为分,rate为double),我是否会遇到与将所有内容存储为double相同的问题?

  2. FastMoney和许多其他库仅支持它们与原始类型之间的操作。如果我无法执行profit.divide(investment)(两者均为FastMoney),我该怎么办才能得到投资回报的准确表示呢?我想这意味着我将两者都转换为double,然后再将它们除以,但这会不准确,对吗?


6
为什么要将货币金额相乘?你经常计算“50美元乘以2.75美元”吗?将金额存储为分只需要在显示时进行格式化,不需要使用任何库。 - Kayaman
5
@Kayaman,你的意思是你不使用“平方美元”吗? - Andy Turner
1
只有当我买方形的鸡蛋时,才需要@AndyTurner。 - Kayaman
我个人更喜欢 Triganic Pu。但你需要有大口袋。 - Stephen C
1
“0.85”不是货币金额,而是汇率。为什么你想要将它存储在long类型中呢? - Kayaman
显示剩余4条评论
1个回答

4

您所寻找的功能已经在JavaMoney Library中实现。

它有一个FastMoney类,可以进行long算术运算,这正是您所要求的。

对于新的Java开发人员-为什么使用long而不是double?

Java中的浮点算术会导致一些意外的精度错误,因此不建议在财务计算中使用。

还请注意,这与long算术计算中的精度损失不同,后者是由于长整型中未存储小数部分造成的。在实现过程中,可以通过将小数部分移动到另一个long中(例如1.05-> 1美元和5美分)来避免这种情况。

参考资料

  1. 快速教程

  2. 项目网站


我认为这是一个足够好的答案。你仍然需要自己阅读规格说明才能使用它。只需提到有一个基于大十进制的Money类和一个基于长整型的FastMoney类即可。 - Veselin Davidov
我不确定是否想使用包装器(例如FastMoney),因为这会创建成千上万个不必要的短暂对象。除了类型安全之外,还有什么好处吗? - Mattx
@Mattx 是的:你把代码的责任放在库上,而不是你自己。此外,你标准化你的代码,以便操作对开发人员隐藏,因为它可能是问题的根源。现在,短暂对象的成本通常是可以忽略的。尝试使用实际的微基准测试进行分析,看看问题是否真的存在。"过早优化是万恶之源。" - Olivier Grégoire
我原本打算使用长整型和一个带有静态方法的接口来隐藏操作逻辑,我贴上的那段代码只是一个例子,实际上它会变成Decimal.multiply(decimal1, decimal2)。不管怎样,我将对FastMoney进行基准测试,并与BigDecimals和long/double进行比较。 - Mattx
在使用FastMoney(用于表示1.0和0.25)进行100万次快速测试计算(1.0+0.25)* 0.5时,与BigDecimal相比,它证明在执行相同任务时速度较慢。不确定原因。 - Mattx

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