Java 中的货币精度(不是 BigDecimal)

Monetary precision in Java (not BigDecimal)

我们知道使用 float 或 double 不是需要正确精度的选项,我们知道 BigDecimal 可以达到这个目的,但我们也知道它比常规原始操作慢大约 100 倍。

现在,如果速度对我们很重要并且我们确实需要精度,我们该怎么办?

我尝试以最慢的单位存储货币价值并将其转换存储为 1 BTC = 100000000 satoshi,但经过几次实验后很明显,您根本无法长期存储 100BTC,超过最大可能值。是的,可以选择牺牲精度,比如存储 microBTC 等,但问题更全球化,我们如何用原语设计这样的东西?

您的选择是:

BigDecimal - 准确有效 - 比原语慢,但可能没有那么明显 - 大部分是不可变的(即可以改变准确性但不能改变价值)。

long - 准确但有值限制 - 原始,因此不能在速度上超越 - 不可变 - 数学更容易和更清晰地编写。

BigInteger - 可能是你在上述两者之间最好的折中所 - 不可变的,所以每当你改变值时你都必须创建新的 - 你不太可能达到它的极限。

正如 D.E.Knuth 在他的 "The Art of Computer Programming" 的第 2 卷中充分记录的那样,以任意精度实现算术不是 "black art" - 参见章节 "Seminumerical Algorithms"。我已经经历过,遵循实现 COBOL 计算的必要性(所以:不仅是整数)。

此外,可以选择在不为每个新运算结果重新创建对象的情况下制作 BigInteger 或 BigDecimal 的类似工作。是的,这意味着工作,但如果你真的认为你需要它...

我发现就算法而言,BigInteger 并没有那么慢。使用它对我来说真正致命的是必须经常在二进制和十进制(十进制数字数组)之间进行转换。