# BigDecimal gives unexpected results for numbers larger than 7 or 0 decimal numbers

#### Tags: bigdecimal, java, math

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()`.

## Why did you get the expected result for 21099000.1 / 13196000.1?

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`.

## Why did you not get the expected result for 21099000.0 / 13196000.0?

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`.

## How can I change this behavior?

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
```

## What is the most common way?

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
```

Source: stackoverflow