While trying to calculate a ratio of the volume of 2 objects, I noticed some weirdness in the calculation, here is a sample you can run for yourself:

public class TestApplication { public static void main(String[] args) { BigDecimal first = BigDecimal.valueOf(21099000.0); BigDecimal second = BigDecimal.valueOf(13196000.0); System.out.println("First: " + first); System.out.println("Second: " + second); System.out.println("Division: " + first.divide(second, RoundingMode.HALF_UP).doubleValue()); } }

And the result is:

First: 2.1099E+7 Second: 1.3196E+7 Division: 0.0

There are 3 ways I could make it give me the expected result

**1. If I change the decimal part from 0 to 1 (or any non-0 number)**:

First: 21099000.1 Second: 13196000.1 Division: 1.6

**2. If I divide the numbers beforehand (make them 7 digit numbers instead of 8)**:

First: 2109900.0 Second: 1319600.0 Division: 1.6

**3. If I specify a scale doing division ( first.divide(second, 0, RoundingMode.HALF_UP)**:

First: 2.1099E+7 Second: 1.3196E+7 Division: 2.0

I thought that BigDecimal is backed by an integer and the numbers I used are way below 2 billion. Can anyone explain what makes these 3 cases different from the original result?

As per the documentation, `divide(BigDecimal divisor, RoundingMode roundingMode)`

returns a `BigDecimal`

whose value is (this / divisor), and whose scale is `this.scale()`

.

Check the result of the following code:

import java.math.BigDecimal; import java.math.RoundingMode; public class Main { public static void main(String[] args) { BigDecimal first = BigDecimal.valueOf(21099000.1); BigDecimal second = BigDecimal.valueOf(13196000.1); System.out.println("First: " + first + ", Scale: " + first.scale()); System.out.println("Second: " + second + ", Scale: " + second.scale()); // 21099000.0 / 13196000.0 = 1.5988936041 System.out.println(BigDecimal.valueOf(1.5988936041).setScale(first.scale(), RoundingMode.HALF_UP)); } }

**Output:**

First: 21099000.1, Scale: 1 Second: 13196000.1, Scale: 1 1.6

As you can see, JVM has chosen the scale as `1`

for `first`

and thus the result of `divide`

(which is `1.5988936041`

) is also set as `1`

which is equal to `1.6`

with `RoundingMode.HALF_UP`

.

Check the result of the following code:

import java.math.BigDecimal; import java.math.RoundingMode; public class Main { public static void main(String[] args) { BigDecimal first = BigDecimal.valueOf(21099000.0); BigDecimal second = BigDecimal.valueOf(13196000.0); System.out.println("First: " + first + ", Scale: " + first.scale()); System.out.println("Second: " + second + ", Scale: " + second.scale()); // 21099000.0 / 13196000.0 = 1.5988936041 System.out.println(BigDecimal.valueOf(1.5988936041).setScale(first.scale(), RoundingMode.HALF_UP)); } }

**Output:**

First: 2.1099E+7, Scale: -3 Second: 1.3196E+7, Scale: -3 0E+3

As you can see, JVM has chosen the scale as `-3`

for `first`

and thus the result of `divide`

(which is `1.5988936041`

) is also set as `-3`

which is equal to `0`

(or `0E+3`

) with `RoundingMode.HALF_UP`

.

As mentioned in the documentation, scale of the division is set as `this.scale()`

which means if you set the scale of `first`

to `1`

, you can get the expected result.

import java.math.BigDecimal; import java.math.RoundingMode; public class Main { public static void main(String[] args) { BigDecimal first = BigDecimal.valueOf(21099000.0).setScale(1); BigDecimal second = BigDecimal.valueOf(13196000.0); System.out.println("First: " + first + ", Scale: " + first.scale()); System.out.println("Second: " + second + ", Scale: " + second.scale()); System.out.println("Division: " + first.divide(second, RoundingMode.HALF_UP).doubleValue()); } }

**Output:**

First: 21099000.0, Scale: 1 Second: 1.3196E+7, Scale: -3 Division: 1.6

The last example worked well and there is no problem using it. However, the most common way is to use `divide(BigDecimal divisor, int scale, RoundingMode roundingMode)`

.

import java.math.BigDecimal; import java.math.RoundingMode; public class Main { public static void main(String[] args) { BigDecimal first = BigDecimal.valueOf(21099000.0); BigDecimal second = BigDecimal.valueOf(13196000.0); System.out.println("First: " + first + ", Scale: " + first.scale()); System.out.println("Second: " + second + ", Scale: " + second.scale()); System.out.println("Division: " + first.divide(second, 1, RoundingMode.HALF_UP).doubleValue()); } }

**Output:**

First: 2.1099E+7, Scale: -3 Second: 1.3196E+7, Scale: -3 Division: 1.6