/*
* 问题产生及解决
*/
@Test
public void test(){
double d1 = 0.1;
double d2 = 0.2;
//问题出现
System.out.println(0.1+0.2);//结果为0.30000000000000004
//解决问题思路1
BigDecimal b1 = new BigDecimal(d1);
BigDecimal b2 = new BigDecimal(d2);
System.out.println(b1.add(b2));
//结果0.3000000000000000166533453693773481063544750213623046875
//解决问题思路2
BigDecimal bb1 = new BigDecimal(Double.toString(d1));
BigDecimal bb2 = new BigDecimal(Double.toString(d2));
System.out.println(bb1.add(bb2));//结果0.3
//查阅JDK_API得知以下写法等同于解决问题思路2
BigDecimal bbb1 = BigDecimal.valueOf(d1);
BigDecimal bbb2 = BigDecimal.valueOf(d2);
System.out.println(bbb1.add(bbb2));//结果0.3
}
使用BigDecimal(double val)构造函数时仍会存在精度丢失问题,建议使用BigDecimal(String val)
摘抄:
- BigDecimal(double val)构造方法的结果有一定的不可预知性。有人可能认为在 Java 中写入 new BigDecimal(0.1) 所创建的 BigDecimal 正好等于 0.1(非标度值 1,其标度为 1),但是它实际上等于 0.1000000000000000055511151231257827021181583404541015625。这是因为 0.1 无法准确地表示为 double(或者说对于该情况,不能表示为任何有限长度的二进制小数)。这样,传入到构造方法的值不会正好等于 0.1(虽然表面上等于该值)。
- String构造方法是完全可预知的:写入 new BigDecimal("0.1") 将创建一个 BigDecimal,它正好等于预期的0.1。因此,比较而言,通常建议优先使用 String 构造方法。
- 当double必须用作 BigDecimal的源时,请注意,此构造方法提供了一个准确转换;它不提供与以下操作相同的结果:先使用
Double.toString(double)
方法,然后使用BigDecimal(String)
构造方法,将 double 转换为 String。 即BigDecimal.valueOf(double d)方法。