为什么不同的计算机里的浮点数会不一样

最近有被问到“你知道为什么不同计算机里的浮点数会不一样吗”

“不太清楚”

“你没有好奇去不同的机器上尝试打印出来吗”

“没有...”

很惭愧,发现自己对这些计算机底层原理还不是很熟,并且自己也没有实际的去尝试过好奇过,人呐,还是要对知识的追求继续保持好奇态度的!

先简单的做个测试,我在mac上计算0.1+0.2,发现出来的值不是0.3,而是0.300000000004. 这不是什么 bug,也不是 Python 有问题,而是浮点数在做运算时必然的结果!

首先我们先看一下浮点数的二进制结构是什么样的,从下图可以看到,第一个是符号位,后面5位是指数区域,剩下的10位就是尾数区域

IEEE 754浮点数格式的科学计数法格式: N = (-1)s* 1.f * 2

 8.5 的例子可以表示为 23 + 1/2 ,是因为 8 和 0.5 刚好都是 2 的次方数,所以完全不会产生任何精准度问题。但如果是 8.9 的话因为没办法换成 2 的次方数相加,所以最后会被迫表示成 1.0001110011… * 23,而且还会产生大概 0.0000003 的误差。这样的误差积少成多,在操作频繁之后就会累积起来越来越大,导致误差明显。比如帧同步中一致性的问题。

 
总结
为什么 0.1 + 0.2 != 0.3 呢?首先,0.1 和 0.2 这两个实数无法用二进制精确表示。在二进制的世界里,只有包含因子 5 的十进制数才有可能精确表示,而 0.1 和 0.2 转换为二进制后是无限循环小数,在计算机中存储的值只能是真实值的近似表示,这里是第一次精度丢失;其次,计算机浮点数采用了 IEEE 754 标准格式,IEEE 754 严格规定了尾数域和指数域可表示的大小,位数有限,意味着可表示的信息量是有限的,换句话说就会存在三种误差:上溢、下溢和舍入误差。而 0.1 + 0.2 的结果的尾数域部分刚好超过了尾数域位数,超过位数的部分舍去,存在舍入误差,这里是第二次精度丢失

如何减少误差呢
  • 在某些语言会提供所谓的 epsilon,用来让你判断是不是在浮点误差的允许范围内,以 Python 来说 epsilon 的值大约是 2.2e-16 
  • 直接用十进制来计算

Reference:
  1. https://juejin.cn/post/6860445359936798734

__EOF__

本文作者cancantrbl
本文链接https://www.cnblogs.com/cancantrbl/p/16069469.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   cancantrbl  阅读(996)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示