`java.math.BigDecimal`

class represents “Immutable, arbitrary-precision signed decimal numbers” (with some limits), and has methods to operate on those numbers. Its use although is not so immediate and it is easy to do errors.

In this article I'll try to put some light on this topic, in the hope of seeing a lowering in the amount of bugs related to code using `BigInteger`

and `BigDecimal`

.

### What is it

The package `java.math`

contains two classes targeted at "arbitrary precision math": `BigInteger`

and `BigDecimal`

. Both handle numbers whose magnitude overcome the limits imposed by standard Java types such as `int`

, `long`

, `double`

, `float`

, ecc.

`java.math.BigInteger`

This class handles **immutable**, integer numbers of arbitrary length; the maximum amount of usable digits is Integer.MAX_VALUE.

`java.math.BigDecimal`

This class handles **immutable**, decimal numbers of arbitrary length; as above, the amount of usable digits is limited by the available memory. It is composed of two parts:

*unscaled value*: it is a`BigInteger`

object holding the number representation withouts the decimal symbol.*scale*: an`int`

number indicating how many decimal digits we have.

So the value of a `BigDecimal`

number is: `unscaled / 10^<sup>scale</sup>`

### What is its purpose?

Floating-point math has some serious drawbacks that makes it impossible to use them in some kind of calculations, especially the financial ones (although some still uses them...you understand my rage now...). Countless bank software are using *fixed point math* to do their calculations: they are simply integer numbers on which is applied a fixed amount of decimal places (even very high). This approach can help mitigate *some* of the anomalies of floating-point math (IEEE 754), but at the price of a more difficult handling.

*java.math. BigDecimal* aim to solve these kind of problems, but they even go further with many useful rounding methods and an impressive high precision.

### How is it used

A fundamental characteristic of `BigInteger`

and `BigDecimal`

is that their instances are **immutable**: all their methods return a **new object** holding the result of the operation. Even methods like `setScale()`

, `movePointLeft() / movePointRight()`

or `negate()`

, that sounds like they're modifying the object, return a new instance with the result.

Some examples:

```
package org.megadix.math;
import java.math.BigDecimal;
public class BigDecimalTest1 {
public static void main(String[] args) {
BigDecimal n1 = new BigDecimal("1000.123482248908085303458975309348");
System.out.println("n1 = " + n1);
BigDecimal n2 = new BigDecimal("2000.122837345398340801010291390210252");
System.out.println("n2 = " + n2);
BigDecimal resultAdd = n1.add(n2);
System.out.println("n1 + n2 = " + resultAdd);
BigDecimal resultMultiply = n1.multiply(n2);
System.out.println("n1 * n2 = " + resultMultiply);
BigDecimal resultDivide = n1.divide(n2, BigDecimal.ROUND_HALF_UP);
System.out.println("n1 / n2 = " + resultDivide);
}
}
```

Output:

```
n1 = 1000.123482248908085303458975309348
n2 = 2000.122837345398340801010291390210252
n1 + n2 = 3000.246319594306426104469266699558252
n1 * n2 = 2000369.817011446171094293893027628836590866233492522879727390461035696
n1 / n2 = 0.500031029882290273171404981367
```

Things to note:

- use of the
`BigDecimal(String)`

constructor. This constructoraccepts an english-like notation: sign, integer part, fraction and exponent. For the detail visit the official documentation (Javadoc); - the result of any operation is a new instance of
`BigDecimal`

; - the
`BigDecimal.toString()`

method is two-way compatible with`BigDecimal(String)`

constructor.

### Formatting

Decimal numbers formatting is a complicated matter:

- language and location: for example in GB or USA commas are used to separate thousands and dots to separate decimals, but in Italy and France it is the opposite;
- alphabet: characters used to represent numbers can vary, think about western, ebraic, arab, hindi...);
- leading/trailing zeroes: ".1", "0.1", ".10", "0.1000", ...
- presence or not of sign symbols (+/-);
- scientific notation;
- ...isn't it enough?

Here is a simple example of formatting that sets language and number of decimal places:

```
package org.megadix.math;
import java.math.BigDecimal;
import java.text.NumberFormat;
import java.util.Locale;
public class BigDecimalTestFormat {
public static void main(String[] args) {
BigDecimal n = new BigDecimal("1000" +
"." +
"00000000000000000000000000000000000000000000000000" +
"1" +
"000");
NumberFormat fmt_EN = NumberFormat.getNumberInstance(Locale.ENGLISH);
fmt_EN.setMaximumFractionDigits(1000);
NumberFormat fmt_IT = NumberFormat.getNumberInstance(Locale.ITALIAN);
fmt_IT.setMaximumFractionDigits(1000);
System.out.println(fmt_EN.format(n));
System.out.println(fmt_IT.format(n));
}
}
```

Output:

```
1,000.000000000000000000000000000000000000000000000000001
1.000,000000000000000000000000000000000000000000000000001
```

Things to note

- the format string has been split into multiple rows for better readability;
- we leveraged the methods of
`java.text.NumberFormat`

for formatting; - we used the
`NumberFormat(java.util.Locale)`

constructor.

### Developments

These article has given you the basics to operate on `BigDecimal`

; anyway, you are strongly encouraged to read the official Java documentation.