float与double在java中很多人都知道有精度问题,对于浮点数不能直接进行比较,下面几个高频的关于浮点数的面试题,你会不会呢?
float a1 = 0.1f;
double a2 = 0.1;
System.out.println((a1 - a2) == 0.0);
float b1 = 0.125f;
double b2 = 0.125;
System.out.println((b1 - b2) == 0.0);
double c1 = 0.625;
double c2 = 0.5;
double c3 = 0.375;
System.out.println((c1 - c2) == (c2 - c3));
double d1 = 0.8;
double d2 = 0.6;
double d3 = 0.4;
System.out.println((d1 - d2) == (d2 - d3));
答案为:
false
true
true
false
我们知道计算机表示数字使用的是二进制。对于整数,转换成二进制比较简单,比如5=101;对于小数,需要对小数的前后部分分开计算,比如5.5=101.1。
详细的讲解参考网上其他内容,例如:http://www.ruanyifeng.com/blog/2010/06/ieee_floating-point_representation.html等
对于整数部分计算成二进制比较简单,对于小数后计算二级制一般采用 乘2取整法
例如:0.3
0.3x2=0.6,取小数后第一位为0,当前为0.0
0.6x2=1.2,取小数后第二位为1,当前为0.01
0.2x2=0.4,取小数后第三位为0,当前为0.010
0.4x2=0.8,取小数后第四位为0,当前为0.0100
0.8x2=1.6,取小数后第五位为1,当前为0.01001
......
我们发现对于小数后计算出来的二进制会出现精度问题,这个时候你已经明白了为什么0.1比较为false,0.125比较为true的原因了
继续深入
System.out.println(1.0 / 0);
System.out.println(0.0 / 0);
System.out.println(1 / 0);
输出:
Infinity
NaN
java.lang.ArithmeticException: / by zero
这个是因为浮点数在二进制中只能表示为大概值,所以在Java中浮点数有无限值和无意义非数字的概念,即Infinity与NaN
但是对于整数,0是不能当作除数的