Reputation: 14296
I have seen there are issues when creating BigDecimal
from double
.
Although FastMoney
doesn't use BigDecimal
(as opposed to Money
), I am not sure how either of them will behave when I crate them from a double
value.
Is creating a FastMoney
/Money
instance from a double
not recommended? Should I always try to create them from String
?
Upvotes: 2
Views: 309
Reputation: 11246
The floating-point types float
and double
are dangerous to use in monetary calculations, but when used to create a JSR-354 MonetaryAmount
, you will be lucky enough:
First, MonetaryAmount
(or at least the reference implementation of FastMoney
, which seems to be what most users prefer) only supports 5 decimal places. If you try to convert a double
such as 0.123456, you'll get an ArithmeticException.
If you try to convert a double that represents a normal typical amount with 2dp, such as FastMoney.of(1.23, "USD")
, this is what will happen:
Your double
argument will be boxed into a Double
and the method FastMoney.of(Double, String)
will be called.
This method will convert your number to a long
value 123000 (representing 1.23000) by calling BigDecimal.valueOf(1.23)
.
BigDecimal.valueOf(1.23)
will use the string from Double.toString(1.23)
.
Double.toString(1.23)
will convert that into "1.23" using the complex rules described in the Javadoc
It so happens that all double numbers 0.00001, 0.00002, ..., 0.99999 get converted to String (and thereby to BigDecimal) as exact decimals using this method.
So, to summarise, you can use double
to create a FastMoney
amount, but you should avoid it.
Upvotes: 1
Reputation: 3201
double
and especially float
types are dangerous. This numbers are base-2 numeral system then it's not possible to represent 0.24F
directly as the same it's not possible to represent 1/3
in decimal system without recurring decimal period i.e. 1/3=0.3333...
or 0.(3)
.
So the float number 0.24F
when printed back to decimal representation is shown as 0.23
with a change due to rounding:
println(0.24F) => 0.23999999463558197021484375
while 0.25F
can be shown directly:
println(0.25F) => 0.25
So answering to your question: it depends. For 0.25, 0.5, 0.75 it's ok to use double.
But the FastMoney class uses not a floating-point arithmetic but a fixed-point arithmetic
Upvotes: 1