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.
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.
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
BigDecimalThere 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-utilVery useful. I was struggling to do precisely calculations. Thanks!!