Encodera

Thanks for reading!

Donate to the site — we work hard for you.

Contents

Math and BigDecimal

For calculations Java has the Math class with ready-made mathematical functions. And when every cent matters, you use the BigDecimal class instead of double — it computes decimal fractions exactly.

The Math class

Math methods are called through the class name; there is no need to create an object. max() and min() pick the larger and the smaller value, abs() gives the absolute value, pow(a, b) raises to a power, sqrt() takes the square root. There are three rounding methods: round() — to the nearest whole number, floor() — down, ceil() — up:

void main() {
    IO.println(Math.max(7, 12));
    IO.println(Math.abs(-5));
    IO.println(Math.pow(2, 10));
    IO.println(Math.sqrt(16));
    IO.println(Math.round(2.5));
    IO.println(Math.floor(2.7));
    IO.println(Math.ceil(2.1));
}

Output:

12
5
1024.0
4.0
3
2.0
3.0

pow, sqrt, floor and ceil return a double, while round returns a whole long. There are constants too: Math.PI is the number π.

The imprecision of double

A double stores a number in binary, and many decimal fractions, such as 0.1, are infinite in binary. So only an approximation is stored, and a tiny error shows up in calculations:

void main() {
    IO.println(0.1 + 0.2);
    IO.println(0.1 + 0.2 == 0.3);
}

Output:

0.30000000000000004
false

For physics or graphics such an error does not matter, but for money it is unacceptable.

BigDecimal

The BigDecimal class stores a decimal number exactly. Create it from a string and calculate with the add(), subtract() and multiply() methods — the usual + and * do not work with objects:

void main() {
    BigDecimal a = new BigDecimal("0.1");
    BigDecimal b = new BigDecimal("0.2");
    IO.println(a.add(b));
 
    BigDecimal price = new BigDecimal("19.99");
    IO.println(price.multiply(new BigDecimal("3")));
}

Output:

0.3
59.97

Rounding to cents

setScale() sets the number of digits after the decimal point, and RoundingMode sets the rounding rule. HALF_UP is the one taught at school: five and above rounds up. Division also needs a precision, otherwise for 10 / 3 Java throws an exception — the result is infinite:

void main() {
    BigDecimal price = new BigDecimal("19.99");
    BigDecimal tax = price.multiply(new BigDecimal("0.2"));
    IO.println(tax);
    IO.println(tax.setScale(2, RoundingMode.HALF_UP));
 
    BigDecimal share = new BigDecimal("10").divide(new BigDecimal("3"), 2, RoundingMode.HALF_UP);
    IO.println(share);
}

Output:

3.998
4.00
3.33

Comparing BigDecimal

The equals() method of BigDecimal also takes the number of decimal places into account: 2.0 and 2.00 are different for it. To compare just the values, use compareTo() — it returns 0 when the numbers are equal:

void main() {
    BigDecimal a = new BigDecimal("2.0");
    BigDecimal b = new BigDecimal("2.00");
    IO.println(a.equals(b));
    IO.println(a.compareTo(b) == 0);
}

Output:

false
true

BigInteger

For whole numbers that do not fit even into a long, there is BigInteger. It works the same way — through methods:

void main() {
    BigInteger big = BigInteger.TWO.pow(100);
    IO.println(big);
}

Output:

1267650600228229401496703205376

Common mistake

If you create a BigDecimal from a double, it faithfully keeps the already imprecise binary value — error and all:

void main() {
    BigDecimal wrong = new BigDecimal(0.1);
    IO.println(wrong);
}

Output:

0.1000000000000000055511151231257827021181583404541015625

Pass a string: new BigDecimal("0.1"). If the number is already in a double, use BigDecimal.valueOf(0.1) — it gives 0.1.

Thanks for reading!

Donate to the site — we work hard for you.