我已经看到从
BigDecimal
创建double
时存在问题。
虽然
FastMoney
不使用 BigDecimal
(与 Money
相反),但我不确定当我从 double
值创建它们时它们会如何表现。
不建议从
FastMoney
创建 Money
/double
实例吗?我应该总是尝试从 String
创建它们吗?
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 就可以了。
浮点类型
float
和 double
在货币计算中使用是危险的,但是当用于创建 JSR-354 MonetaryAmount
时,你会足够幸运:
首先,
MonetaryAmount
(或者至少是FastMoney
的参考实现,这似乎是大多数用户喜欢的)仅支持5位小数。如果您尝试转换 double
(例如 0.123456),您将收到 ArithmeticException。
如果你尝试用 2dp 转换代表正常典型金额的 double,例如
FastMoney.of(1.23, "USD")
,将会发生以下情况:
您的
double
参数将被装箱到 Double
中,并且方法 FastMoney.of(Double, String)
将被调用。
此方法将通过调用
long
将您的号码转换为 BigDecimal.valueOf(1.23)
值 123000(代表 1.23000)。
BigDecimal.valueOf(1.23)
将使用 Double.toString(1.23)
中的字符串。
Double.toString(1.23)
将使用 Javadoc 中描述的复杂规则将其转换为“1.23”
碰巧所有双数 0.00001, 0.00002, ..., 0.99999 使用此方法转换为 String(从而转换为 BigDecimal)作为精确小数。
因此,总而言之,您可以使用
double
来创建FastMoney
金额,但您应该避免使用它。