美文网首页
Java中的浮点数比较

Java中的浮点数比较

作者: jiangmo | 来源:发表于2018-02-08 10:30 被阅读100次
System.out.println(0.1d == 0.1f);  

返回:false
原因:精度丢失,比较结果是不对的。
底层原理是什么呢,我们来看看:

类型升级(type promotion)

java中的几种原生的数值类型进行==或!=等比较运算时,如果运算符两边的数值类型不同,则首先会进行类型升级(type promotion),规则如下:

  • 如果运算符任意一方的类型为double,则另一方会转换为double
  • 否则,如果运算符任意一方的类型为float,则另一方会转换为float
  • 否则,如果运算符任意一方的类型为long,则另一方会转换为long
  • 否则,两边都会转换为int

上面那个例子,float首先会被升级为double,然后执行浮点数相等比较。那为什么会返回flase呢?

舍入误差(round-off error)

根据IEEE 754,单精度的float是32位,双精度的double为64位,如下图:


其中,第一部分(s)为符号位,第二部分(exponent)为指数位,第三部分(mantissa)为基数部分。 这是科学计数法的二进制表示。

那么,既然位数是固定的,要表示像 1/3=0.3333333333333...或者pi=3.1415926..... 这样的无限循环小数,就变得不可能了。

根据规范,则需要将不能标识的部分舍掉。

第二,还与10进制不同的是,二进制对于一些有限的小数,也不能精确的标示。比如像0.1这样的小数,用二进制也无法精确表示。所以,也需要舍掉。

关于0.1无法用二进制精确表示,可以参见文章: http://en.wikipedia.org/wiki/Floating_point

科学计数法及浮点数的二进制表示

254可以有但不仅仅有以下几种表示:


但是如果基数是2,需要怎么转换呢?

单精度转换为双精度会发生什么

单精度浮点数0.1表示成二进制会是什么样子的:
System.out.println(Integer.toBinaryString(Float.floatToIntBits(0.1f)));
结果是:111101110011001100110011001101
然后,双精度的浮点数0.1的二进制会是什么样子呢:

System.out.println(Long.toBinaryString(Double.doubleToLongBits(0.1d)));

结果是:11111110111001100110011001100110011001100110011001100110011010
然后,在比较float==double的时候,首先,会将float进行类型升级,得到的新的double 的值会是什么样子:
System.out.println(Long.toBinaryString(Double.doubleToLongBits(0.1f)));
结果是:11111110111001100110011001100110100000000000000000000000000000

经过转换后的double的值已经和直接赋值的double的值不相等了。所以这样用==比较返回的值是false

System.out.println(Integer.toBinaryString(Float.floatToIntBits(0.1f)));  
System.out.println(Long.toBinaryString(Double.doubleToLongBits(0.1d)))  
System.out.println(Long.toBinaryString(Double.doubleToLongBits(0.1f)));

在进行浮点数比较的时候,主要需要考虑3个因素

  • NaN
  • 无穷大/无穷小
  • 舍入误差

在要求精确的场合,请使用BigDecimal

根据需要自行判断

Math.abs(a-b) 判断精度范围

==、equal、compareTo都不靠谱,可以看起源码

Ref:
http://blog.csdn.net/wcxiaoych/article/details/42806313

相关文章

  • Java中的浮点数比较

    返回:false原因:精度丢失,比较结果是不对的。底层原理是什么呢,我们来看看: 类型升级(type promot...

  • 浮点数的比较&初识String

    小心使用浮点数进行比较 浮点数没有绝对的相等,只有近似的相等。Java中只有整数才有绝对的相等。 例如: 结果:t...

  • Java浮点数常见面试题解析

    float与double在java中很多人都知道有精度问题,对于浮点数不能直接进行比较,下面几个高频的关于浮点数的...

  • Java比较浮点数的正确方式

    今天在读《Java开发手册》时,看到浮点数的等值判断问题「浮点数的基本数据类型不能用 == 比较,包装数据类型不能...

  • JAVA中的浮点数

    概念 浮点数,是相对于定点数来说的,下面分别对两种数的表达方式进行一个简单的介绍 注意,这边的浮点数均已单精度的浮...

  • java 两个double比较大小

    在java中会经常遇到两个浮点类型比较大小的问题,要注意的是浮点数只是一个近似值,比如,1/3在java中是不会通...

  • JAVA浮点类型数据计算

    摘要 Java浮点数据类型在内存中存储会出现精度丢失的情况,因此涉及浮点数据类型的计算需使用BigDecimal类...

  • Java中的比较?

    参考Java基础之comparator和comparable的区别以及使用 1.== 和 equals的区别 2....

  • 浮点数有精确度问题

    当计算中包含小数时,很多网友建议不要使用浮点数(搜索IEEE754),浮点数有精度问题。Java中有专门的工业级高...

  • Java中的一些基础知识点整理

    Java中的数据类型: 基本数据类型:整数: byte, short, int(default), long浮点数...

网友评论

      本文标题:Java中的浮点数比较

      本文链接:https://www.haomeiwen.com/subject/nqdozxtx.html