BigDecimal in Java

The BigDecimal in java class provides operations for arithmetic (add, subtract, multiply, divide), scale manipulation, rounding, comparison, hashing, and format conversion. The BigDecimal represents immutable, arbitrary-precision signed decimal numbers. This class shall be used in the necessity of high-precision calculation.

Comparing BigDecimals

The method compareTo should be used to compare BigDecimals:

BigDecimal a = new BigDecimal(5);
a.compareTo(new BigDecimal(0)); // a is greater, returns 1
a.compareTo(new BigDecimal(5)); // a is equal, returns 0
a.compareTo(new BigDecimal(10)); // a is less, returns -1

Commonly you should not use the equals method since it considers two BigDecimals equal only if they are equal in value and also scale:

BigDecimal a = new BigDecimal(5);
a.equals(new BigDecimal(5)); // value and scale are equal, returns true
a.equals(new BigDecimal(5.00)); // value is equal but scale is not, returns false

Using BigDecimal instead of float

Due to the way that the float type is represented in computer memory, the results of operations using this type can be inaccurate – some values are stored as approximations. Good examples of this are monetary calculations. If high precision is necessary, other types should be used. e.g. Java 7 provides BigDecimal.

Related Article: Mathematical operations with BigDecimal in Java

import java.math.BigDecimal;
public class FloatTest {
public static void main(String[] args) {
float accountBalance = 10000.00f;
System.out.println("Operations using float:");
System.out.println("1000 operations for 1.99");
for(int i = 0; i<1000; i++){
accountBalance -= 1.99f;
}
System.out.println(String.format("Account balance after float operations: %f",
accountBalance));
BigDecimal accountBalanceTwo = new BigDecimal("10000.00");
System.out.println("Operations using BigDecimal:");
System.out.println("1000 operations for 1.99");
BigDecimal operation = new BigDecimal("1.99");
for(int i = 0; i<1000; i++){
accountBalanceTwo = accountBalanceTwo.subtract(operation);
}
System.out.println(String.format("Account balance after BigDecimal operations: %f",
accountBalanceTwo));
}

Output of this program is:

Operations using float:
1000 operations for 1.99
Account balance after float operations: 8009,765625
Operations using BigDecimal:
1000 operations for 1.99
Account balance after BigDecimal operations: 8010,000000

For a starting balance of 10000.00, after 1000 operations for 1.99, we expect the balance to be 8010.00. Using the float type gives us an answer around 8009.77, which is unacceptably imprecise in the case of monetary calculations. Using BigDecimal gives us the proper result.

BigDecimal.valueOf()

The BigDecimal class contains an internal cache of frequently used numbers e.g. 0 to 10. The BigDecimal.valueOf() methods are provided in preference to constructors with similar type parameters i.e. in the below example a is preferred to b.

BigDecimal a = BigDecimal.valueOf(10L);    //Returns cached Object reference
BigDecimal b = new BigDecimal(10L);        //Does not return cached Object reference

BigDecimal a = BigDecimal.valueOf(20L);    //Does not return cached Object reference
BigDecimal b = new BigDecimal(20L);        //Does not return cached Object reference

BigDecimal a = BigDecimal.valueOf(15.15); //Preferred way to convert a double (or float) into a
BigDecimal, as the value returned is equal to that resulting from constructing a BigDecimal from the
result of using Double.toString(double)
BigDecimal b = new BigDecimal(15.15);    //Return unpredictable result

Leave a Comment