0

I am trying to convert string values into BigDecimal and then perform my calculation, but the output is not as expected. Please find the code below:

import java.math.BigDecimal;
import java.math.RoundingMode;

public class Test {
    public static void main(String[] args) {
        BigDecimal b1 = new BigDecimal("320000");
        BigDecimal b2 = new BigDecimal(0.1);
        BigDecimal b3 = new BigDecimal("9.6");

        BigDecimal b5 = new BigDecimal(320000);
        BigDecimal b6 = new BigDecimal(9.6);

        BigDecimal b4 = (
          b1.multiply(b2)
        ).multiply(
          b3.divide(b1, RoundingMode.HALF_UP)
        );
        System.out.println(b4.setScale(4, RoundingMode.HALF_UP));

        BigDecimal b7 = (
          b5.multiply(b2)
        ).multiply(
          b6.divide(b5, RoundingMode.HALF_UP)
        );
        System.out.println(b7.setScale(4, RoundingMode.HALF_UP));
    }
}

The out is shown below for both the instances:

0.0000
0.9600

When I use the instantiate the numbers as BigDecimal rather than converting them from string in the second instance I am getting the desired output.

Can you please let me know why it is happening and how could I get the desired output of 0.9600 in the first instance.

user207421
  • 305,947
  • 44
  • 307
  • 483
Ranit Das
  • 64
  • 1
  • 11
  • Aren't those two totally different calculations? – g00se Jun 24 '23 at 15:42
  • Nope...they are the same calculation....In the first case I am converting string to BigDecimal and then performing the calculation....in the second case no conversion is happening before calculation – Ranit Das Jun 24 '23 at 15:53
  • Does [this](https://stackoverflow.com/questions/40487561/bigdecimal-add-strange-behavior) answer your question? – Asgar Jun 24 '23 at 15:53
  • It might have something to do with "scale", as `new BigDecimal("9.6")` has a scale of 1, but `new BigDecimal(9.6)` has a scale of 49 (due to `9.6` actual being `9.5999999999999996447286321199499070644378662109375`). – Progman Jun 24 '23 at 15:58
  • There is always a conversion. Either from a floating point literal or from a string. Using floating point gives unexpected results. It is gives more intuitive results to use string initializing. – aled Jun 24 '23 at 19:15
  • Reduce your problem, because this is a bad question right now: the difference is not at the "final number", the difference already manifests after a single operation, so reduce your code to show _that_ and then ask about that. If, after reducing, you can't figure out why things are different. Because just because you write `9.6`, that doesn't mean the floating point number _is_ 9.6, because it's not. There is no true 9.6 in IEEE floats. `new BigDecimal("9.6")` is 9.6, `new BigDecimal(9.6)` _is not that value at all_. – Mike 'Pomax' Kamermans Jun 24 '23 at 21:55
  • Don't use `new BigDecimal(0.1)`. Use `new BigDecimal("0.1")`. – user207421 Jun 25 '23 at 04:01

1 Answers1

1

"... Can you please let me know why it is happening and how could I get the desired output of 0.9600 in the first instance."

For your division, remove the RoundingMode argument.

b3.divide(b1)

When a RoundingMode is specified, the scale will be derived.

Here is the source code used internally by BigDecimal, for that method.
OpenJDK – GitHub – jdk/src/java.base/share/classes/java/math/BigDecimal.java.

In your inner division, it will use a scale of 1, from 9.6.

b3.divide(b1, RoundingMode.HALF_UP)

So, this will return 0.0, while the actual answer is 0.00003.

As a note, if needed, you can specify the scale as the second parameter; BigDecimal#divide.

b3.divide(b1, 5, RoundingMode.HALF_UP)
Reilas
  • 3,297
  • 2
  • 4
  • 17