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

Java中两个float计算



问题的产生

今天同学问了我一个问题,给了一段代码,问运行结果: 第一眼看上去感觉就是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.
经验分享 程序员 微信小程序 职场和发展