Search code examples
javabigdecimal

BigDecimal to values monetary


I have two float values:

float value1 = 1.9f;
float value2 = 20;

I want to multiply them and get an exact result, so I use BigDecimal and expect 38 as result:

BigDecimal total = new BigDecimal(value1).multiply(new BigDecimal(value2));

System.out.println(total); // 37.99999952316284179687500

When I do the same test with 10 and 1.9, I get 18.99999976158142089843750 instead of 19.

Why do I lose precision?


Solution

  • This is explained in the javadoc for the BigDecimal(double) constructor:

    The results of this constructor can be somewhat unpredictable. One might assume that writing new BigDecimal(0.1) in Java creates a BigDecimal which is exactly equal to 0.1 (an unscaled value of 1, with a scale of 1), but it is actually equal to 0.1000000000000000055511151231257827021181583404541015625. This is because 0.1 cannot be represented exactly as a double (or, for that matter, as a binary fraction of any finite length). Thus, the value that is being passed in to the constructor is not exactly equal to 0.1, appearances notwithstanding.

    And although your variables are floats, there is not ctor that takes floats, so they are cast as doubles. And like the docs say, if you used Strings for your values, you would get the exact result (38) you expect.