Golang中浮点数(float)不能直接比较详解

2023-06-01 详解 浮点数 Golang

为什么不是直接进行 == 比较而是需要写一个方法来进行比较?

答:

浮点数在计算计中的存储是通过二进制的方式进行存储会存在一个精度丢失的问题。


看看浮点数的精度问题:

浮点数[0]的二进制为[0-00000000-00000000000000000000000]
浮点数[0.000000000000000000000000000000000000000000001]的二进制为[0-00000000-00000000000000000000001]

浮点数[16777216]的二进制为[0-10010111-00000000000000000000000]
浮点数[16777217]的二进制为[0-10010111-00000000000000000000000]

上面第2行是float32能表示的最接近0的小数了,再小的话表示不了。此时精度非常高。

但随着数字离0越来越远,即除去符号位,数字越来越大,精度会慢慢丢失,原因是指数位能表示的小数点偏移量最大127。

那么浮点数越大,小数点就越往右移,此时存储时右边被截断的数字就越多,精度自然就丢失了。

可以看出第3/4两行,16777216与16777217的浮点数存储居然是一样的,此时的最小精度已经大于1了。


比较float是否相等的函数

const MIN = 0.000001
// IsEqual
// 判断 float 是否相等
func IsEqual(x, y float64) bool {
    return math.Abs(x-y) < MIN
}


总结

开发过程中,极端情况下,一个大数与另一个小数进行操作,容易出现精度丢失严重导致结果误差大的问题。

所以一般我们建议不要用单精度float32,而是用双精度float64,增加的8字节让指数位和数据位都增大了,精度自然有所提高,使用更安全




相关文章