浮点型变量在进行计算的时候会出现丢失精度的问题,所以,在需要用到金钱的地方要用BigDecimal而不是其他,如下代码段。
public class Main {
public static void main(String[] args) {
System.out.println(0.05+2.05);
System.out.println(1.5-1.05);
System.out.println(1.0455*100);
System.out.println(123.3 / 100);
}
}
输出:
2.0999999999999996
0.44999999999999996
104.55000000000001
1.2329999999999999
如果用浮点表示,那么我们在进行商品价格计算的时候,就会出现问题,可能我们有0.06元,却无法购买一个0.05元和一个0.01元的商品,因为他们两个的总和可能为0.060000000000000005。
所以,一般我们用BigDecimal来表示金额,当然在数据库中也要使用decimal,不用float或double,也可以用用int或者long存储金额,单位为”分“。
但是BigDecimal使用不当也会造成精度丢失,下面是BigDecimal的部分构造器,以及常用方法。
BigDecimal(int) 创建一个具有参数所指定整数值的对象。
BigDecimal(double) 创建一个具有参数所指定双精度值的对象。
BigDecimal(long) 创建一个具有参数所指定长整数值的对象。
BigDecimal(String) 创建一个具有参数所指定以字符串表示的数值的对象。
add(BigDecimal) BigDecimal对象中的值相加,然后返回这个对象。
subtract(BigDecimal) BigDecimal对象中的值相减,然后返回这个对象。
multiply(BigDecimal) BigDecimal对象中的值相乘,然后返回这个对象。
divide(BigDecimal) BigDecimal对象中的值相除,然后返回这个对象。
toString() 将BigDecimal对象的数值转换成字符串。
doubleValue() 将BigDecimal对象中的值以双精度数返回。
floatValue() 将BigDecimal对象中的值以单精度数返回。
longValue() 将BigDecimal对象中的值以长整数返回。
intValue() 将BigDecimal对象中的值以整数返回。
如下测试代码,结果貌似更为过分。
public class Main {
public static void main(String[] args) {
BigDecimal bigDecimal1 = new BigDecimal(0.05);
BigDecimal bigDecimal2 = new BigDecimal(0.01);
BigDecimal bigDecimal3 = new BigDecimal(122.11);
System.out.println(bigDecimal1.add(bigDecimal2));
System.out.println(bigDecimal3.toString());
}
}
输出结果:
0.06000000000000000298372437868010820238851010799407958984375
122.1099999999999994315658113919198513031005859375
其实也好解决,使用他的BigDecimal(String)
构造方法即可。
public class Main {
public static void main(String[] args) {
BigDecimal bigDecimal1 = new BigDecimal("0.05");
BigDecimal bigDecimal2 = new BigDecimal("0.01");
BigDecimal bigDecimal3 = new BigDecimal("122.11");
System.out.println(bigDecimal1.add(bigDecimal2));
System.out.println(bigDecimal3.toString());
}
}
输出结果:
0.06
122.11
所以我们一般使用BigDecimal来解决商业运算上丢失精度的问题的时候,声明BigDecimal对象的时候一定要使用它构造参数为String的类型的构造器。
其实,在BigDecimal(double val)构造器上是有注释已经说明了这个问题的,大概意思是说,如果有人使用new BigDecimal(0.1)
创建一个BigDecimal对象,那他的实际值等于0.1000000000000000055511151231257827021181583404541015625
,但如果使用new BigDecimal("0.1")
这样去创建,则最终值会是你可预测的。