【问题标题】:Java fast money representation?Java 快钱表示法?
【发布时间】:2018-05-28 07:16:27
【问题描述】:

我正在开发一个实时应用程序,该应用程序使用 BigDecimal 处理不同货币和汇率的货币,但是我面临一些严重的性能问题,我想更改基础表示。

我一遍又一遍地读到,在 Java 中表示货币的一种快速的好方法是使用 long 存储美分(或任何所需的精度)。正如其中一位 cmets 指出的那样,有一些带有包装器的库可以做到这一点,例如来自 JavaMoney 的 FastMoney。

这里有两个问题。

  1. 将钱长期存放(或在包装内)并将其他所有内容(如汇率)保持为双倍是否总是安全?换句话说,如果我这样做Math.round(money * rate)(钱是美分,汇率是双倍),我会不会遇到基本相同的问题?

  2. FastMoney 和许多其他库仅支持它们与原始类型之间的操作。如果我不能做到profit.divide(investment)(两者都是FastMoney),我应该如何准确表示投资回报。我想我的想法是我将两者都转换为双精度然后将它们分开,但这不准确吗?

【问题讨论】:

  • 为什么要将货币金额相乘?您是否经常计算“50 美元乘以 2.75 美元”?将金额存储为美分只需要您为显示进行格式化,您不需要任何库。
  • @Kayaman 你的意思是你使用平方美元?
  • @AndyTurner 仅在我购买方形鸡蛋时。
  • 我自己更喜欢Triganic Pu。但你需要大口袋。
  • 0.85 不是货币金额,而是汇率。为什么要长期保存?

标签: java currency long-integer java-money jsr354


【解决方案1】:

您正在寻找的功能已在 JavaMoney 库中实现。

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

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

Java 中的浮点运算由于其实现而导致一些意想不到的精度错误。因此不建议在财务计算中使用。

另请注意,这与 long 算术计算中的精度损失不同,这是由于小数部分未存储在 long 中。这可以在实施过程中通过将小数部分移动到另一个多头(例如 1.05 -> 1 美元和 5 美分)来防止。

参考文献

  1. A Quick Tutorial

  2. Project Website

【讨论】:

  • 我认为这个答案已经足够好了。您仍然需要自己阅读规范才能使用它。只需提一下,有一个基于大十进制的 Money 类和基于多头的 FastMoney。
  • 我不确定是否要使用包装器(即 FastMoney),它会创建成千上万个不必要的短期对象。除了类型安全还有什么好处?
  • @Mattx 是的:你把代码的责任放在了库而不是你身上。此外,您还可以标准化您的代码,以便对开发人员隐藏操作,因为它可能是问题的根源。如今,短寿命对象的成本通常可以忽略不计。尝试使用实际的微基准进行分析,看看问题是否真的存在。 “过早的优化是万恶之源。”
  • 我打算用longs和一个静态方法的接口来隐藏操作的逻辑,我粘贴的代码只是一个例子,实际上它会变成 Decimal.multiply(decimal1, decimal2) .无论如何,我将对 FastMoney 进行基准测试,并将其与 BigDecimals 和 long/double 作为基准进行比较。
  • 在使用 FastMoney(表示 1.0 和 0.25)进行的快速测试计算 (1.0+0.25)*0.5 100 万次时,对于相同的任务,它被证明比 BigDecimal 慢。不知道为什么。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-02-26
  • 1970-01-01
  • 2011-03-25
  • 1970-01-01
  • 2013-11-29
  • 2023-03-21
  • 2018-04-16
相关资源
最近更新 更多