【Java】Java中两个float计算得出错误结果

来源:互联网 发布:大数据走势 找规律 编辑:程序博客网 时间:2024/06/05 19:54

Java中两个float计算


  • Java中两个float计算
    • 问题的产生
    • 原因
    • 如何解决
    • 使用Java的到浮点数的二进制


问题的产生

今天同学问了我一个问题,给了一段代码,问运行结果:
这里写图片描述
第一眼看上去感觉就是0.8啊,没毛病,可是要是这么简单的题怎么会问我呢,感觉是个陷阱啊,这时候想起来,浮点数的存储不是精确的,但是依然得不出答案,于是上IDE编译运行了一遍。
这里写图片描述
结果:0.79999995
其实不只是减法,加法也可能发生这种情况,可以参考 这里。是不是很奇怪呢,让我们一起去探索究竟。

原因

浮点数在内存中是按照IEEE754标准进行存储的,详细的介绍请Google或者百度,或者参考这篇文章 得到浮点数的二进制。
原因就是计算机内部是通过二进制也就是0和1来存储数据的,浮点数也不例外,但是有些浮点数是无法精确存储的,看了上面那篇文章应该可以理解,只有由2的幂组成的数才可以精确存储。

2.0f在内存中可以准确的存储,这是2.0f的二进制存储图:
这里写图片描述

1.2f就无法精确的存储:
这里写图片描述

经过换算可以得到1.2f在内存中存储的其实是 1.2000000476837158203125E0
这里就可以体现出浮点数是在一定精度内还是准确的。

因为1.2f后面还有很多多余的数字,进行减法就相当于计算:
2.0 - 1.2000000476837158203125E0
它的结果就是0.7999999523162842
进行保留后就得到了我们输出的结果0.79999995

如何解决

通过java.math包中提供的BigDecimal类可以解决此类问题。
这里写图片描述

也一定要使用BigDecimal类中参数类型为String的构造函数
这里写图片描述

不然还是的不到正确的结果:
这里写图片描述

这是因为以String为参数的构造函数内部是采用字符串处理的,而以浮点数为参数,内部还是通过double类型实现,所以还是会出现精度损失的问题。

使用Java的到浮点数的二进制

得到浮点数的二进制这篇文章是使用C语言得到浮点数的二进制,使用java比C语言要简单,因为有方法可以调用。

可以使用Float类的静态方法floatToIntBits()或者floatToRawIntBits():
这里写图片描述

floatToIntBits()和floatToRawIntBits()的区别就在于当参数是NaN,floatToRawIntBits 不压缩所有将 NaN 编码为一个“规范”NaN 值的位模式。
这里写图片描述

If the argument is NaN, the result is the integer representing the actual NaN value. Unlike the floatToIntBits method, floatToRawIntBits does not collapse all the bit patterns encoding a NaN to a single “canonical” NaN value.

0 0
原创粉丝点击