java基础之浮点数演算

java基础之浮点数运算

与整型数据不同,浮点数是采用“符号位+指数+有效位(尾数)”的存储方式,介于这种存储的特殊性,所以只占4字节的float类型数据却可以比占了8字节的long类型数据有着更大的取值范围。然而,这也是要付出一定的代价的,具体情况如下。
1.浮点数只是近似的存储
浮点数的缺陷1

public class FloatTest1 {
      public static void main(String[] args) {
            int intMax=Integer.MAX_VALUE;
            int intMin=Integer.MIN_VALUE;
            long longMax=Long.MAX_VALUE;
            long longMin=Long.MIN_VALUE;
            float fintMax=intMax;
            float fintMin=intMin;
            double dlongMax=longMax;
            double dlongMin=longMin;
            System.out.println(“int类型的最大值是:”+intMax);
            System.out.println(“使用float存储后为:”+fintMax);
            System.out.println(“int类型的最小值是:”+intMin);
            System.out.println(“使用float存储后为:”+fintMin);
            System.out.println(“long类型的最大值是:”+longMax);
            System.out.println(“使用float存储后为:”+dlongMax);
            System.out.println(“long类型的最小值是:”+longMin);
            System.out.println(“使用float存储后为:”+dlongMin);
      }
}

运行结果如下:
int类型的最大值是:2147483647
使用float存储后为:2.14748365E9
int类型的最小值是:-2147483648
使用float存储后为:-2.14748365E9
long类型的最大值是:9223372036854775807
使用float存储后为:9.223372036854776E18
long类型的最小值是:-9223372036854775808
使用float存储后为:-9.223372036854776E18
从结果为我们得知,无论是使用float类型的变量来存储数值,还是用doubel类型的变量来存储数值,都损失了一定的精度,在使用浮点数来输出时,都未能输出准确的结果。
浮点数的缺陷2
我们再来测试一下涌浮点数来存储较小的数据。

public class FloatTest2 {
      public static void main(String[] args) {
            for(float f=0.1f;f<1;f+=0.1){
                  System.out.println(f);
            }
            for(double d=0.1f;d<1;d+=0.1){
                  System.out.println(d);
            }
      }
}

运行结果如下:
0.1
0.2
0.3
0.4
0.5
0.6
0.70000005
0.8000001
0.9000001
0.10000000149011612
0.20000000149011612
0.30000000149011613
0.40000000149011616
0.5000000014901161
0.6000000014901161
0.7000000014901161
0.8000000014901161
0.900000001490116
从结果可知,虽然在计算的时候每次递增0.1,然而结果却是如此的不尽人意。从两个例子可以得出:不论是存储达的数值,还是小的数值,浮点数都不是十分的 准确。浮点数在计算机中只是近似的存储,类似于1/3这样的无限小数,用浮点数也不能准确地表示出来。这里需要注意的是,在第二个例子中,我们看到 0.1~0.6的输出结果是正确的,而从0.7开始才出现误差。其实是我们的眼睛受骗了。
在执行float f=0.1f时,计算机中的数据并不是纯粹的0.1,而是类似于0.1000~000xxx的形式,其中000~000表示若干个0,xxx表示若干个数 字,假设其数据为0.1000000000111111,而folat类型只能保留7~8位有效数字,这样就会从中间截断,从而float存储的值成为 0.10000000,即浮点数值0.1。
2.浮点数的大小比较

public class FloatTest3 {
      public static void main(String[] args) {
            double d1=0.1;
            double d2=0.2;
            double d3=d1+d2;
            if(d1+d2==0.3){
                 System.out.println(“d1+d2==0.3″);
            }else{
                 System.out.println(“d1+d2!=0.3″);
                 System.out.println(d3);
            }
      }
} 

结果如下:
d1+d2!=0.3
0.30000000000000004
再次说明,浮点数的存储是有一定的误差的,所以,不要用浮点数进行相等的比较,也不要进行混合比较(如int与float的比较)。
3.数量级相差很大时浮点数的运算
在使用浮点数时,还需要注意一点,那就是不要再数量级相差太大的数之间进行加减运算,这样可能无法改变原数量级较大的操作数。情况下例:

public class FloatTest4 {
      public static void main(String[] args) {
            float f1=16777216f;
            float f2=f1+1;
            if(f1==f2){
                System.out.println(“f1等于f2″);
            }else{
                 System.out.println(“f1不等于f2″);
            }
            System.out.println(“f1=”+f1);
            System.out.println(“f2=”+f2);
      }
}

结果如下:
f1等于f2
f1=1.6777216E7
f2=1.6777216E7
这与浮点数的内部表示有关,这里可以不必理会浮点数复杂的存储原理,只要明白浮点数毕竟只是近似的存储,而且其存储值越大时,损失的精度也越大,对其进行数量级相差较大的加减元素按就会得不到想要的结果。有什么问题或见解,欢迎来八零客团队博客 来讨论,80客团队成员随时欢迎!后续会讲解确保结果准确性的java类。

本文转载自:http://www.balingke.com/archives/737.html