1.两个在定义时的区别

1)float型 内存分配4个字节,占32位,范围从10^-38到10^38 和 -10^38到-10^-38
        例float x=123.456f,y=2e20f; 注意float型定义的数据末尾必须有"f"或"F",为了和double区别

        (2)double型 内存分配8个字节,范围从10^-308到10^308 和 -10^-308到-10^-308
        例double x=1234567.98,y=8980.09d; 末尾可以有"d"也可以不写

    直接使用 +,-,*,%运算符的问题

 

public class Test{
         public static void main(String args[]){
         System.out.println(0.05+0.01);
         System.out.println(1.0-0.42);
         System.out.println(4.015*100);
         System.out.println(123.3/100);
         }
     }

    结果:
 

0.060000000000000005
     0.5800000000000001
     401.49999999999994    1.2329999999999999

 

原因:

把源程序翻译成二进制的机器码后才能被计算机识别。以上面提到的情况为例,我们源程序里的2.4是十进制的,计算机不能直接识别,要先编译成二进制。但问 题来了,2.4的二进制表示并非是精确的2.4,反而最为接近的二进制表示是2.3999999999999999。原因在于浮点数由两部分组成:指数和尾数,这点如果知道怎样进行浮点数的二进制与十进制转换,应该是不难理解的。如果在这个转换的过程中,浮点数参与了计算,那么转换的过程就会变得不可预 知,并且变得不可逆。我们有理由相信,就是在这个过程中,发生了精度的丢失。而至于为什么有些浮点计算会得到准确的结果,应该也是碰巧那个计算的二进制与 十进制之间能够准确转换。而当输出单个浮点型数据的时候,可以正确输出,如

double d = 2.4;
 System.out.println(d);

不进行浮点计算的时候,在十进制里浮点数能正确显示。这更印证了我以上的想法,即如果浮点数参与了计算,那么浮点数二进制与十进制间的转换过程就会变得不可预知,并且变得不可逆。

       事实上,浮点数并不适合用于精确计算,而适合进行科学计算。这里有一个小知识:既然float和double型用来表示带有小数点的数,那为什么我们不称 它们为“小数”或者“实数”,要叫浮点数呢?因为这些数都以科学计数法的形式存储。当一个数如50.534,转换成科学计数法的形式为5.053e1,它 的小数点移动到了一个新的位置(即浮动了)。可见,浮点数本来就是用于科学计算的,用来进行精确计算实在太不合适了。

解决方法:

 

简化bigdecimal计算的小工具类

在《Effective   Java》这本书中也提到这个原则,float和double只能用来做科学计算或者是工程计算,在商业计算中我们要用java.math.BigDecimal。使用BigDecimal并且一定要用String来够造。

如果我们要做一个加法运算,需要先将两个浮点数转为String,然后够造成BigDecimal,在其中一个上调用add方法,传入另一个作为参数,然后把运算的结果(BigDecimal)再转换为浮点数。你能够忍受这么烦琐的过程吗?网上提供的工具类Arith来简化操作。它提供以下静态方法,包括加减乘除和四舍五入:   

 

public   static   double   add(double   v1,double   v2)   
 public   static   double   sub(double   v1,double   v2)   
 public   static   double   mul(double   v1,double   v2)   
 public   static   double   div(double   v1,double   v2)   
 public   static   double   div(double   v1,double   v2,int   scale)   
 public   static   double   round(double   v,int   scale)  1. import java.math.BigDecimal;    
2.   
3. /** 
4.  * 进行BigDecimal对象的加减乘除,四舍五入等运算的工具类 
5.  * @author ameyume 
6.  * 
7.  */
8. public class Arith {    
9.   
10. /**  
11.     * 由于Java的简单类型不能够精确的对浮点数进行运算,这个工具类提供精  
12.     * 确的浮点数运算,包括加减乘除和四舍五入。  
13.     */
14. //默认除法运算精度  
15.     private static final int DEF_DIV_SCALE = 10;    
16.            
17. //这个类不能实例化  
18.     private Arith(){    
19.     }    
20.   
21. /**  
22.      * 提供精确的加法运算。  
23.      * @param v1 被加数  
24.      * @param v2 加数  
25.      * @return 两个参数的和  
26.      */
27.     public static double add(double v1,double v2){    
28.         BigDecimal b1 = new BigDecimal(Double.toString(v1));    
29.         BigDecimal b2 = new BigDecimal(Double.toString(v2));    
30.         return b1.add(b2).doubleValue();    
31.     }    
32.        
33. /**  
34.      * 提供精确的减法运算。  
35.      * @param v1 被减数  
36.      * @param v2 减数  
37.      * @return 两个参数的差  
38.      */
39.     public static double sub(double v1,double v2){    
40.         BigDecimal b1 = new BigDecimal(Double.toString(v1));    
41.         BigDecimal b2 = new BigDecimal(Double.toString(v2));    
42.         return b1.subtract(b2).doubleValue();    
43.     }    
44.        
45. /**  
46.      * 提供精确的乘法运算。  
47.      * @param v1 被乘数  
48.      * @param v2 乘数  
49.      * @return 两个参数的积  
50.      */
51.     public static double mul(double v1,double v2){    
52.         BigDecimal b1 = new BigDecimal(Double.toString(v1));    
53.         BigDecimal b2 = new BigDecimal(Double.toString(v2));    
54.         return b1.multiply(b2).doubleValue();    
55.     }    
56.   
57. /**  
58.      * 提供(相对)精确的除法运算,当发生除不尽的情况时,精确到  
59.      * 小数点以后10位,以后的数字四舍五入。  
60.      * @param v1 被除数  
61.      * @param v2 除数  
62.      * @return 两个参数的商  
63.      */
64.     public static double div(double v1,double v2){    
65.         return div(v1,v2,DEF_DIV_SCALE);    
66.     }    
67.   
68. /**  
69.      * 提供(相对)精确的除法运算。当发生除不尽的情况时,由scale参数指  
70.      * 定精度,以后的数字四舍五入。  
71.      * @param v1 被除数  
72.      * @param v2 除数  
73.      * @param scale 表示表示需要精确到小数点以后几位。  
74.      * @return 两个参数的商  
75.      */
76.     public static double div(double v1,double v2,int scale){    
77.         if(scale<0){    
78.             throw new IllegalArgumentException(    
79. "The scale must be a positive integer or zero");    
80.         }    
81.         BigDecimal b1 = new BigDecimal(Double.toString(v1));    
82.         BigDecimal b2 = new BigDecimal(Double.toString(v2));    
83.         return b1.divide(b2,scale,BigDecimal.ROUND_HALF_UP).doubleValue();    
84.     }    
85.   
86. /**  
87.      * 提供精确的小数位四舍五入处理。  
88.      * @param v 需要四舍五入的数字  
89.      * @param scale 小数点后保留几位  
90.      * @return 四舍五入后的结果  
91.      */
92.     public static double round(double v,int scale){    
93.         if(scale<0){    
94.             throw new IllegalArgumentException(    
95. "The scale must be a positive integer or zero");    
96.         }    
97.         BigDecimal b = new BigDecimal(Double.toString(v));    
98.         BigDecimal one = new BigDecimal("1");    
99.         return b.divide(one,scale,BigDecimal.ROUND_HALF_UP).doubleValue();    
100.     }    
101.        
102. /**  
103.     * 提供精确的类型转换(Float)  
104.     * @param v 需要被转换的数字  
105.     * @return 返回转换结果  
106.     */
107.     public static float convertsToFloat(double v){    
108.         BigDecimal b = new BigDecimal(v);    
109.         return b.floatValue();    
110.     }    
111.        
112. /**  
113.     * 提供精确的类型转换(Int)不进行四舍五入  
114.     * @param v 需要被转换的数字  
115.     * @return 返回转换结果  
116.     */
117.     public static int convertsToInt(double v){    
118.         BigDecimal b = new BigDecimal(v);    
119.         return b.intValue();    
120.     }    
121.   
122. /**  
123.     * 提供精确的类型转换(Long)  
124.     * @param v 需要被转换的数字  
125.     * @return 返回转换结果  
126.     */
127.     public static long convertsToLong(double v){    
128.         BigDecimal b = new BigDecimal(v);    
129.         return b.longValue();    
130.     }    
131.   
132. /**  
133.     * 返回两个数中大的一个值  
134.     * @param v1 需要被对比的第一个数  
135.     * @param v2 需要被对比的第二个数  
136.     * @return 返回两个数中大的一个值  
137.     */
138.     public static double returnMax(double v1,double v2){    
139.         BigDecimal b1 = new BigDecimal(v1);    
140.         BigDecimal b2 = new BigDecimal(v2);    
141.         return b1.max(b2).doubleValue();    
142.     }    
143.   
144. /**  
145.     * 返回两个数中小的一个值  
146.     * @param v1 需要被对比的第一个数  
147.     * @param v2 需要被对比的第二个数  
148.     * @return 返回两个数中小的一个值  
149.     */
150.     public static double returnMin(double v1,double v2){    
151.         BigDecimal b1 = new BigDecimal(v1);    
152.         BigDecimal b2 = new BigDecimal(v2);    
153.         return b1.min(b2).doubleValue();    
154.     }    
155.   
156. /**  
157.     * 精确对比两个数字  
158.     * @param v1 需要被对比的第一个数  
159.     * @param v2 需要被对比的第二个数  
160.     * @return 如果两个数一样则返回0,如果第一个数比第二个数大则返回1,反之返回-1  
161.     */
162.         public static int compareTo(double v1,double v2){    
163.         BigDecimal b1 = new BigDecimal(v1);    
164.         BigDecimal b2 = new BigDecimal(v2);    
165.         return b1.compareTo(b2);    
166.     }   
167.   
168. }

第三部分: 浮点数大小的比较

 

  • 如果是 double类型,可以直接通过 == 来比较
  • 如果是 Double类型,不可以直接通过 == 来比较,需要使用 compareTo 方法

示例如下:

public static void main(String[] args) throws Exception{

    double v1 = 1234567d;
    double v2 = 1234567d;

    Double v3 = 1234567d;
    Double v4 = 1234567d;

    System.out.println("v1 == v2: " + (v1 == v2));

    System.out.println("v3 == v4: " + (v3 == v4));

    System.out.println("v3.compareTo(v3): " + (v3.compareTo(v4)));
}

public static void main(String[] args) throws Exception{

    double v1 = 1234567d;
    double v2 = 1234567d;

    Double v3 = 1234567d;
    Double v4 = 1234567d;

    System.out.println("v1 == v2: " + (v1 == v2));

    System.out.println("v3 == v4: " + (v3 == v4));

    System.out.println("v3.compareTo(v3): " + (v3.compareTo(v4)));
}

结果如下:

v1 == v2: true
v3 == v4: false