How to calculate monetary values in Java
There are many monetary values calculation in the financial or e-commerce application, and there is one question that arises for this – Should we use double
or float
data type to represent the monetary values?
Answer: Always uses java.math.BigDecimal
to represent the monetary values.
1. Double or Float?
Here is an example of using double
and float
to represent the monetary values in Java.
JavaMoney.java
package com.mkyong;
import java.text.DecimalFormat;
public class JavaMoney {
private static DecimalFormat df = new DecimalFormat("0.00");
public static void main(String[] args) {
System.out.println(2.00 - 1.1);
System.out.println(2.00 - 1.2);
System.out.println(2.00 - 1.3);
System.out.println(2.00 - 1.4);
System.out.println(2.00 - 1.5);
System.out.println(2.00 - 1.6);
System.out.println(2.00 - 1.7);
System.out.println(2.00 - 1.8);
System.out.println(2.00 - 1.9);
System.out.println(2.00 - 2);
System.out.println("--------------------");
double i = 2.0;
double j = 1.7;
System.out.println("double : " + (i - j));
System.out.println("double : " + df.format(i - j));
float i2 = 2.0f;
float j2 = 1.7f;
System.out.println("float : " + (i2 - j2));
System.out.println("float : " + df.format(i2 - j2));
}
}
Output – It cannot calculate all the decimals precisely.
0.8999999999999999
0.8
0.7
0.6000000000000001
0.5
0.3999999999999999
0.30000000000000004
0.19999999999999996
0.10000000000000009
0.0
--------------------
double : 0.30000000000000004
double : 0.30
float : 0.29999995
float : 0.30
2. BigDecimal
To avoid the decimal issue above, we can use BigDecimal
to represent the monetary values; furthermore, we can control the BigDecimal
scale much more straightforward.
JavaMoney2.java
package com.mkyong;
import java.math.BigDecimal;
import java.math.RoundingMode;
public class JavaMoney2 {
public static void main(String[] args) {
System.out.println("--- BigDecimal-----");
System.out.println(BigDecimal.valueOf(2.00).subtract(BigDecimal.valueOf(1.1)));
System.out.println(BigDecimal.valueOf(2.00).subtract(BigDecimal.valueOf(1.2)));
System.out.println(BigDecimal.valueOf(2.00).subtract(BigDecimal.valueOf(1.3)));
System.out.println(BigDecimal.valueOf(2.00).subtract(BigDecimal.valueOf(1.4)));
System.out.println(BigDecimal.valueOf(2.00).subtract(BigDecimal.valueOf(1.5)));
System.out.println(BigDecimal.valueOf(2.00).subtract(BigDecimal.valueOf(1.6)));
System.out.println(BigDecimal.valueOf(2.00).subtract(BigDecimal.valueOf(1.7)));
System.out.println(BigDecimal.valueOf(2.00).subtract(BigDecimal.valueOf(1.8)));
System.out.println(BigDecimal.valueOf(2.00).subtract(BigDecimal.valueOf(1.9)));
System.out.println(BigDecimal.valueOf(2.00).subtract(BigDecimal.valueOf(2)));
System.out.println("--------------------");
BigDecimal i = BigDecimal.valueOf(2.0);
BigDecimal j = BigDecimal.valueOf(1.7);
System.out.println("double : " + i.subtract(j));
System.out.println("double : " + i.subtract(j).setScale(5, RoundingMode.HALF_UP));
}
}
Output – BigDecimal
performs exact decimal arithmetic.
--- BigDecimal-----
0.9
0.8
0.7
0.6
0.5
0.4
0.3
0.2
0.1
0.0
--------------------
double : 0.3
double : 0.30000
how java decides the double precision
ex:
10.2*2 = 20.4
10.3*3=30.599999999999998
why the result is different in both cases?
I also no idea how it works, better use
BigDecimal
There is a library JavaMoney that simplifies a lot of things https://javamoney.org/
Url is updated https://javamoney.github.io/
Thanks for the third party library.
See https://github.com/subes/invesdwin-util#decimal for an alternative to working with Double directly by using a fluent API around it that is very fast since being designed for financial strategy backtesting.
Thanks for your idea,
invesdwin-util
Very useful. I was struggling to do precisely calculations. Thanks!!