从双倍创建 FastMoney/Money 是否有任何注意事项?

问题描述 投票:0回答:2

已经看到

BigDecimal
创建
double
时存在问题。

虽然

FastMoney
不使用
BigDecimal
(与
Money
相反),但我不确定当我从
double
值创建它们时它们会如何表现。

不建议从

FastMoney
创建
Money
/
double
实例吗?我应该总是尝试从
String
创建它们吗?

precision java-money jsr354
2个回答
1
投票

double
,特别是
float
类型是危险的。该数字是基于 2 的数字系统,因此无法直接表示
0.24F
,同样,如果没有重复的小数点,即
1/3
1/3=0.3333...
,则无法在十进制系统中表示
0.(3)

因此,当打印回十进制表示形式时,浮点数

0.24F
显示为
0.23
,并由于舍入而发生变化:

println(0.24F) => 0.23999999463558197021484375

0.25F
可以直接显示:

println(0.25F) => 0.25

所以回答你的问题:这要看情况。对于 0.25、0.5、0.75,使用 double 就可以了。

但是 FastMoney 类使用的不是 浮点算术 而是 定点算术


0
投票

浮点类型

float
double
在货币计算中使用是危险的,但是当用于创建 JSR-354
MonetaryAmount
时,你会足够幸运:

首先,

MonetaryAmount
(或者至少是
FastMoney
的参考实现,这似乎是大多数用户喜欢的)仅支持5位小数。如果您尝试转换
double
(例如 0.123456),您将收到 ArithmeticException。

如果你尝试用 2dp 转换代表正常典型金额的 double,例如

FastMoney.of(1.23, "USD")
,将会发生以下情况:

  1. 您的

    double
    参数将被装箱到
    Double
    中,并且方法
    FastMoney.of(Double, String)
    将被调用。

  2. 此方法将通过调用

    long
    将您的号码转换为
    BigDecimal.valueOf(1.23)
    值 123000(代表 1.23000)。

  3. BigDecimal.valueOf(1.23)
    将使用
    Double.toString(1.23)
    中的字符串。

  4. Double.toString(1.23)
    将使用 Javadoc

    中描述的复杂规则将其转换为“1.23”
  5. 碰巧所有双数 0.00001, 0.00002, ..., 0.99999 使用此方法转换为 String(从而转换为 BigDecimal)作为精确小数。

因此,总而言之,您可以使用

double
来创建
FastMoney
金额,但您应该避免使用它。

© www.soinside.com 2019 - 2024. All rights reserved.