In my example, getAmount()
returns 123456789123123424113.31
.
No, it does not. That is not a value that a double
can represent exactly.
You can easily verify that with this code:
double d = 123456789123123424113.31d;
System.out.println(d);
Which outputs
1.2345678912312343E20
This value has the minimum amount of digits to uniquely distinguish it from any other double
value. Meaning that there aren't any more relevant digits in that double
. You've already lost the precision before converting the value to BigDecimal
.
While an integer data type such as long
and int
can exactly represent every (integer) value within its range, the same can't be said about floating point numbers: they have an immense range of values that they can represent, but at the cost of not being able to represent every possible value within the range. Effectively there's a limited number of digits that a floating point number can represent (about 16 decimal digits for double
and about 7 decimal digits for float
). Everything else will be cut off.
If you need arbitrary precision then something like BigDecimal
can help: it will allocate as much memory as necessary to hold all digits (or round according to your specification, if required), making it much more complex but also more powerful.
BigDecimal bd = new BigDecimal("123456789123123424113.31");
System.out.println(bd);
will print
123456789123123424113.31
Make sure not to initialize the BigDecimal
from a double
value, as you'll only get the cut-off value even then.