Why use BigDecimal instead of Double? (Java)

Serdar A.
3 min readOct 1, 2024

--

Hi Everyone;

Most developers don’t use Double type in projects like financial transactions, certain result expected etc.Because using Double Type causes a lot of problems.

For example :

See below code:

public class DoubleTypeExample {

public static void main(String[] args) {

double d1 = 0.05;
double d2 = 0.03;

double r1 = d1-d2;

System.out.println(r1);

double d3 = 0.03;
double d4 = 0.02;

double r2 = d3-d4;

System.out.println(r2);

double d5 = 0.3;
double d6 = 0.2;

double r3 = d5-d6;
}
}

Result :

0.020000000000000004
0.009999999999999998
0.09999999999999998

You can see that there is something a wrong in results. Error rate is low but why did this happen?

double type has specific certainty. Due to this specific certainty, we face some problems while converting, working maths problems with very big and very small value etc.

double type follows IEEE754 standart when store a value. Due to that, expected result can be different from real result. This is huge problem while working/processing in financial systems.

In general, if a person works in financial system (money, credit etc), he/she has to know that using which decimal process, precision etc. Because in general this situation causes illegal transaction/process.

Solution:

Using BigDecimal

Immutable, arbitrary-precision signed decimal numbers. A BigDecimal consists of an arbitrary precision integer unscaled value and a 32-bit integer scale. (Oracle)

BigDecimal is part of Java (java.math.BigDecimal) It is used in financial/scientific etc. systems.

For example :

 public static void main(String[] args) {

double d1 = 0.05;
double d2 = 0.03;

double r1 = d1-d2;

System.out.println("Double r1 : " + r1);

BigDecimal b1 = new BigDecimal("0.05");
BigDecimal b2 = new BigDecimal("0.03");

BigDecimal b3 = b1.subtract(b2);

System.out.println("BigDecimal b3 : " + b3);

double d3 = 0.03;
double d4 = 0.02;

double r2 = d3-d4;

System.out.println("Double r2 : " + r2);

BigDecimal b4 = new BigDecimal("0.03");
BigDecimal b5 = new BigDecimal("0.02");

BigDecimal b6 = b4.subtract(b5);

System.out.println("BigDecimal b6 : " + b6);

double d5 = 0.3;
double d6 = 0.2;

double r3 = d5-d6;

System.out.println("Double r3 : " + r3);

BigDecimal b7 = new BigDecimal("0.3");
BigDecimal b8 = new BigDecimal("0.2");

BigDecimal b9 = b7.subtract(b8);

System.out.println("BigDecimal b9 : " + b9);
}

Result :

Double r1      : 0.020000000000000004
BigDecimal b3 : 0.02
Double r2 : 0.009999999999999998
BigDecimal b6 : 0.01
Double r3 : 0.09999999999999998
BigDecimal b9 : 0.1

Is it completely resolved?

I think, not completely.

BigDecimal can not resolve some situation. For example : If we divide 10 by 3 result is 3.333….

See below code :

 BigDecimal b10 = new BigDecimal("10");
BigDecimal b11 = new BigDecimal("3");

BigDecimal b12 = b10.divide(b11);

System.out.println("BigDecimal b12 : " + b12);

Error in console :

Exception in thread "main" java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.
at java.base/java.math.BigDecimal.divide(BigDecimal.java:1766)

How to resolve?

BigDecimal b10 = new BigDecimal("10");
BigDecimal b11 = new BigDecimal("3");

BigDecimal b12 = b10.divide(b11,4, RoundingMode.HALF_UP);

System.out.println("BigDecimal b12 : " + b12);

Result :

BigDecimal b12 : 3.3333
  • HALF_UP : Rounding mode to round towards “nearest neighbor” unless both neighbors are equidistant, in which case round up
  • 4 : scale parameter.

Performance?

BigDecimal can be slower than Double. Because BigDecimal stores very big number and uses more memory. So it can be slower than Double.

But if you want certainty, you have to use BigDecimal.

I hope it can be useful for you.

--

--

Serdar A.
Serdar A.

Written by Serdar A.

Senior Software Developer & Architect at Havelsan Github: https://github.com/serdaralkancode #Java & #Spring & #BigData & #React & #Microservice