为什么浮点数不能直接比较大小?
相信大家都了解过在java中1.8-0.8的结果不是我们所期望的0.2,而是0.19999999999999996.可是有人去想过这是什么原因吗.
那好,我们一块来讨论一下java中浮点数精度的那些事儿吧.
java遵循IEEE754浮点数运算规范,使用分数和指数来表示浮点数.如:
0.5:1/2
0.75:1/2 + 1/4
0.875:1/2 + 1/4 + 1/8
……….
因为牵扯无限循环的问题,所以无法精确表示,进而造成运算上的误差.
下面我们来看一个例子,第一次看到这个输入结果时,真的是崩溃的,相信很多初学者也觉得颠覆三观了吧.
package dongmy;
public class Exer1 {
public static void main(String[] args) {
// TODO Auto-generated method stub
double a = 0.1;
double b = 0.1;
double c = 0.1;
if((a + b + c) == 0.3) {
System.out.println("等于0.3");
}
else {
System.out.println("不等于0.3");
}
}
}
怎么样,是不是想都不用想呢,因为谁还不知道0.1 + 0.1 + 0.1等于0.3啊.可是,继续往下看吧!
是的,你没有看错.结果显示的是"不等于0.3".为什么呢?
没错,这是因为浮点数误差的关系,那么我们应该怎么做来得到更好的精确度呢!
诺,来看使用java.math.BigDecimal后的效果吧.
package dongmy;
import java.math.BigDecimal;
public class EXer3 {
public static void main(String[] args) {
BigDecimal a = new BigDecimal("0.1");
BigDecimal b = new BigDecimal("0.1");
BigDecimal c = new BigDecimal("0.1");
BigDecimal d = new BigDecimal("0.1");
if(a.add(b).add(c).equals(d)) {
System.out.println("等于0.3");
}
else {
System.out.println("不等于0.3");
}
}
}
使用java.math.BigDecimal类后,BigDecimal提供add()方法,equals()方法,add()方法会返回代表运算结果的BigDecimal,直接利用返回的BigDecimal再调用add()方法,最后通过调用equals()方法比较两个BigDecimal是否相同.
java中浮点数的计算
话不多说,直接以第一个说的那个"1.0-0.8不等于0.2"问题来给个程序体会体会.
使用java.math.BigDecimal类解决问题的代码如下:
package dongmy;
import java.math.BigDecimal;
public class EXer2 {
public static void main(String[] args) {
BigDecimal a = new BigDecimal("1.0");
BigDecimal b = new BigDecimal("0.8");
BigDecimal c = a.subtract(b);
System.out.println(c);
}
}
这样使用java.math.BigDecimal类后,我们终于可以看到期待的结果0.2了.
为什么呢!这个类是不是很神奇呢...
详情请看下述总结
总结:
BigDecimal在创建时会剖析传入字符串,以默认精度进行接下来的运算.
BigDecimal提供plus(), substract(), multiply(), divide()等方法,可以进行加减乘除运算,这些方法都会返回代表运算结果的BigDecimal.所以直接利用返回的BigDecimal,再通过调用BigDecimal提供的方法,就可以起到提高运算精度的作用了.
怎么样,有没有感觉到神奇呢?嘿嘿,快去敲几个高精度运算的例子练练手吧.