概述
浮点数的表示
在计算机系统中,浮点数采用 符号+阶码+尾数 进行表示。
在Java中,单精度浮点数float类型占32位,它的二进制表示方式为:
- 符号位:1位,0表示正数; 1表示负数
- 指数位:8位,用来表示指数(要加上偏移量)
- 小数位:23位,用来表示小数
实际上计算机中的浮点数表示方法和科学技术法类似,小数的位数决定了浮点数的精度。当一个十进制的小数转换成二进制时,很有可能无法使用这么多小数位表示它。因此使用浮点数的时候,实际存储的尾数是被截取或者舍入之后的值。因此使用浮点数进行计算的时候就不得不考虑精度问题,即浮点数无法精确计算。
如何比较浮点数
对于浮点数,我们无法使用==或者包装类型的equals()来精确比较,尽管无法做到精确比较,但是我们可以确定一个误差范围,当小于这个误差范围的时候就认为这两个浮点数相等。
也可以使用BigDecimal,BigDecimal 是不可变的,它能够精确地表示十进制数字。需要注意的是,创建 BigDecimal 对象时,要使用参数为 String 的构造方法,不要使用构造参数为 double 的,如果非要使用 double 创建,一定要用 valueOf 静态方法,防止丢失精度。然后调用 compareTo 方法比较即可。
为什么使用double的构造参数就会丢失精度?
代码:
System.out.println(new BigDecimal(0.99D)); // 0.9899999999999999911182158029987476766109466552734375
System.out.println(BigDecimal.valueOf(0.99D)); // 0.99
输出:
表面上看起来第一行数字更长,但是我们传的是0.99,它却是0.98…所以损失了精度
public static BigDecimal valueOf(double val) {
return new BigDecimal(Double.toString(val));
}
那么使用BigDecimal.valueOf(double val)
就一定精确吗?
不是。
代码:
double val = 0.989999999999999111D;
System.out.println(Double.toString(val)); //0.9899999999999991
System.out.println(BigDecimal.valueOf(val)); //0.9899999999999991
当数值超过了double的精度范围,Double.toString()
方法也是无法精确表示的。要使用参数为 String 的构造方法才能保证compareTo()
的结果是精确的。
System.out.println(new BigDecimal("0.989999999999999111")); //0.989999999999999111
代码
如果可以确保数值不会超过double的精度范围,一定要比较两个浮点型大小,比如不会出现0.989999999999999111
这样超过double所能表示的范围的数值,那么:
public static int doubleCompare(double a, double b) {
BigDecimal bd1 = BigDecimal.valueOf(a);
BigDecimal bd2 = BigDecimal.valueOf(b);
return bd1.compareTo(bd2);
}
来自:
Java比较两个浮点数 - zhloong - 博客园
Java比较浮点数的正确方式 - 简书
Java中new BigDecimal()和BigDecimal.valueOf() - djangson小站
java - BigDecimal - to use new or valueOf - Stack Overflow
BigDecimal如何使用new或valueOf? - 问答 - 云+社区 - 腾讯云
new BigDecmal (double)精度问题及与BigDecimal.valueOf(double)的区别_u013514816的博客-CSDN博客
最后
以上就是陶醉太阳为你收集整理的java中如何比较两个浮点型大小的全部内容,希望文章能够帮你解决java中如何比较两个浮点型大小所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复