在项目当中,对于double类型数据的使用比较频繁。尤其是处理金钱相关的数据,在使用Double类型的数据时,涉及到精度,显示,四舍五入等等问题。
1. 显示问题,当double 数据 小于 0.0001 大于等于 10000000时,直接转为String输出时,会显示为科学计数法。
1: double double1 = 0.00009;
2: System.out.println(double1); // 9.0E-5
3: 4: double double2 = 10000000;
5: System.out.println(double2); // 1.0E7
需要使用DecimalFormat 转化输出
1: DecimalFormat formate = new DecimalFormat("#.######");
2: System.out.println(formate.format(double1)); //0.00009
3: 4: formate = new DecimalFormat("########.##");
5: System.out.println(formate.format(double2));//10000000
这里面会有四舍五入问题:
1: double double1 = 0.000096789;
2: DecimalFormat formate = new DecimalFormat("#.######");
3: System.out.println(formate.format(double1)); //0.000097
当取小数点后六位时,会在第七位四舍五入。
2. 误差问题,两个Double类型的数,进行运算。经常会产生误差。
1: System.out.println(0.05 + 0.01); //0.060000000000000005
2: System.out.println(1.0 - 0.42); //0.5800000000000001
3: System.out.println(4.015 * 100); //401.49999999999994
4: System.out.println(123.3 / 100); //1.2329999999999999
看似简单的计算,结果却出人意料。解决方法是将Double转为BigDecimal。调用BigDecimal的 运算。
1: double d1 = 0.05;
2: double d2 = 0.01;
3: BigDecimal b1 = new BigDecimal(Double.toString(d1));
4: BigDecimal b2 = new BigDecimal(Double.toString(d2));
5: System.out.println(b1.add(b2)); //0.06
需要注意的是,如果new BigDecimal()时使用的是double类型的构造方法。问题依旧是可能存在的,这边要使用String参数的构造方法。
3. 两个double比较的问题。将double数的运算结果和0比较。由于精度问题,比如if(1-0.999999999999999999 == 0.0) 这个是成立的。
附上double数的运算:
1: /**
2: * 两个Double数相加
3: *
4: * @param v1
5: * @param v2
6: * @return
7: */
8: public static double doubleAdd(Double v1, Double v2) {
9: 10: BigDecimal b1 = new BigDecimal(v1.toString());
11: 12: BigDecimal b2 = new BigDecimal(v2.toString());
13: 14: return b1.add(b2).doubleValue();
15: 16: } 17: 18: /**
19: * 两个Double数相减
20: *
21: * @param v1
22: * @param v2
23: * @return
24: */
25: public static double doubleSub(Double v1, Double v2) {
26: 27: BigDecimal b1 = new BigDecimal(v1.toString());
28: 29: BigDecimal b2 = new BigDecimal(v2.toString());
30: 31: return b1.subtract(b2).doubleValue();
32: 33: } 34: 35: /**
36: * 两个Double数相乘
37: *
38: * @param v1
39: * @param v2
40: * @return
41: */
42: public static double doubleMul(Double v1, Double v2) {
43: 44: BigDecimal b1 = new BigDecimal(v1.toString());
45: 46: BigDecimal b2 = new BigDecimal(v2.toString());
47: 48: return b1.multiply(b2).doubleValue();
49: 50: } 51: 52: /**
53: * 两个Double数相除
54: *
55: * @param v1
56: * @param v2
57: * @return
58: */
59: public static double doubleDiv(Double v1, Double v2) {
60: 61: BigDecimal b1 = new BigDecimal(v1.toString());
62: 63: BigDecimal b2 = new BigDecimal(v2.toString());
64: 65: return b1.divide(b2, DEF_DIV_SCALE, BigDecimal.ROUND_HALF_UP)
66: .doubleValue(); 67: 68: } 69: 70: /**
71: * 两个Double数相除,并保留scale位小数
72: *
73: * @param v1
74: * @param v2
75: * @param scale
76: * @return
77: */
78: public static double doubleDiv(Double v1, Double v2, int scale) {
79: 80: if (scale < 0) {
81: 82: throw new IllegalArgumentException(
83: 84: "The scale must be a positive integer or zero");
85: 86: }87: int DEF_DIV_SCALE = 10;
88: 89: BigDecimal b1 = new BigDecimal(v1.toString());
90: 91: BigDecimal b2 = new BigDecimal(v2.toString());
92: 93: return b1.divide(b2, scale, BigDecimal.ROUND_HALF_UP).doubleValue();
94: 95: }