Java中的简单浮点数类型float和double不能够进行精确运算。
请看下面实例:
1public class Test{
2 public static void main(String args[]){
3 System.out.println(0.05+0.01);
4 System.out.println(1.0-0.42);
5 System.out.println(4.015*100);
6 System.out.println(123.3/100);
7 }
8}
9
其运行结果如下:
0.060000000000000005
0.5800000000000001
401.49999999999994
1.2329999999999999
在《Effective Java》这本书中也提到这个原则,float和double只能用来做科学计算或者是工程计算,在商业计算中我们要用
java.math.BigDecimal。
我们如果需要精确计算,非要用String来够造BigDecimal不可!
下面的这个工具类是是转载别人的,可以通过个工具类实现小数的精确计算。
1import java.math.BigDecimal;
2/** *//**
3* 由于Java的简单类型不能够精确的对浮点数进行运算,这个工具类提供精
4* 确的浮点数运算,包括加减乘除和四舍五入。
5*/
6public class Arith{
7 //默认除法运算精度
8 private static final int DEF_DIV_SCALE = 10;
9 //这个类不能实例化
10 private Arith(){
11 }
12
13 /** *//**
14 * 提供精确的加法运算。
15 * @param v1 被加数
16 * @param v2 加数
17 * @return 两个参数的和
18 */
19 public static double add(double v1,double v2){
20 BigDecimal b1 = new BigDecimal(Double.toString(v1));
21 BigDecimal b2 = new BigDecimal(Double.toString(v2));
22 return b1.add(b2).doubleValue();
23 }
24 /** *//**
25 * 提供精确的减法运算。
26 * @param v1 被减数
27 * @param v2 减数
28 * @return 两个参数的差
29 */
30 public static double sub(double v1,double v2){
31 BigDecimal b1 = new BigDecimal(Double.toString(v1));
32 BigDecimal b2 = new BigDecimal(Double.toString(v2));
33 return b1.subtract(b2).doubleValue();
34 }
35 /** *//**
36 * 提供精确的乘法运算。
37 * @param v1 被乘数
38 * @param v2 乘数
39 * @return 两个参数的积
40 */
41 public static double mul(double v1,double v2){
42 BigDecimal b1 = new BigDecimal(Double.toString(v1));
43 BigDecimal b2 = new BigDecimal(Double.toString(v2));
44 return b1.multiply(b2).doubleValue();
45 }
46
47 /** *//**
48 * 提供(相对)精确的除法运算,当发生除不尽的情况时,精确到
49 * 小数点以后10位,以后的数字四舍五入。
50 * @param v1 被除数
51 * @param v2 除数
52 * @return 两个参数的商
53 */
54 public static double div(double v1,double v2){
55 return div(v1,v2,DEF_DIV_SCALE);
56 }
57
58 /** *//**
59 * 提供(相对)精确的除法运算。当发生除不尽的情况时,由scale参数指
60 * 定精度,以后的数字四舍五入。
61 * @param v1 被除数
62 * @param v2 除数
63 * @param scale 表示表示需要精确到小数点以后几位。
64 * @return 两个参数的商
65 */
66 public static double div(double v1,double v2,int scale){
67 if(scale<0){
68 throw new IllegalArgumentException(
69 "The scale must be a positive integer or zero");
70 }
71 BigDecimal b1 = new BigDecimal(Double.toString(v1));
72 BigDecimal b2 = new BigDecimal(Double.toString(v2));
73 return b1.divid(b2,scale,BigDecimal.ROUND_HALF_UP).doubleValue();
74 }
75
76 /** *//**
77 * 提供精确的小数位四舍五入处理。
78 * @param v 需要四舍五入的数字
79 * @param scale 小数点后保留几位
80 * @return 四舍五入后的结果
81 */
82 public static double round(double v,int scale){
83 if(scale<0){
84 throw new IllegalArgumentException(
85 "The scale must be a positive integer or zero");
86 }
87 BigDecimal b = new BigDecimal(Double.toString(v));
88 BigDecimal one = new BigDecimal("1");
89 return b.divid(one,scale,BigDecimal.ROUND_HALF_UP).doubleValue();
90 }
91 }
92