一文简单明了说明为什么 float64 float32 会有精确缺失的问题

2022-07-13 00:13:04 +08:00
 8520ccc

说明

取值范围

2382 次点击
所在节点    程序员
14 条回复
yayiji
2022-07-13 00:35:07 +08:00
用范围容易理解,但我总喜欢另一个角度,就是数制

比如,十进制的 0.1 在二进制中是个无限循环小数,所以使用有限的二进制无论如何也无法精确表示 0.1

也即是说,即便不考虑范围问题,对于很多确定十进制小数二进制也无能为力,比如说,麻烦用二进制精确存储 0.1 0.2 0.3 0.4 0.5 这五个数吧
8520ccc
2022-07-13 00:39:54 +08:00
@yayiji 这种说法比较绕,直接用范围不用考虑那么多,明白原理就行
ruixue
2022-07-13 00:43:51 +08:00
@yayiji 0.5 的二进制不就是 0.1 吗
yayiji
2022-07-13 00:55:53 +08:00
@8520ccc 因为还有数制本身的问题,比如说,我只想存十进制的 0.1 ,其他数不考虑了,这时仍然无法精确存储
yeqizhang
2022-07-13 00:58:02 +08:00
用的了这么复杂么,精度缺失不就是一句话: 因为算出来的都是近似值。只是 float 定的规则,长度固定的情况下,小数点前面越长,小数点后面位数就越短,偏差就会越来越大。

你算出来是 2^64 也是不对的,肯定不止这么点的。用的科学表示法,能表达的数值的数量你以为跟整形能算的出来?
yeqizhang
2022-07-13 01:00:23 +08:00
额,我看错了,你说的二进制的个数呀,那是我说错了🌚
hsfzxjy
2022-07-13 01:02:33 +08:00
@yeqizhang 不是不止这么点,而是不到 2^64 个,nan 要占掉很多个位
Jooooooooo
2022-07-13 01:07:19 +08:00
真的不如 "一个有限十进制小数无法用有限二进制小数" 表达来的简单

按照你这个说法, 很难解释出 0.1+0.2 怎么不等于 0.3 呢
hsfzxjy
2022-07-13 01:07:48 +08:00
感觉不同人的盲点还是不一样的。有的人就是知道了浮点数不能表示所有实数,但还是迷惑「哎呀 0.1 这么简单的数怎么就不能表示」。这时就要和他用进制解释。
haolongsun
2022-07-13 01:12:14 +08:00
复习一下 IEEE754 标准,不知道肯定大学计组不过关,推荐 csapp 。
hxysnail
2022-07-13 08:27:06 +08:00
想要回答这个问题,需要理解 IEEE754 ,它采用科学计数法,位数是有限的。而 0.1 在二进制中,是一个无穷的循环小数,没有办法用科学计数法精确表示。

https://fasionchan.com/posts/ieee754-traps/
DOLLOR
2022-07-13 09:42:22 +08:00
我感觉大家把两件事混在一起谈了。

一是,一个数在十进制下是有限小数,但在二进制下是无限小数,导致浮点数无法精确表示对应的十进制数。

二是,浮点数所表达的数字,它的绝对值越大,精度越低。以至于当它要表达的数字超过 MAX_SAFE_INTEGER 或 MIN_SAFE_INTEGER 之后,连整数都不能精确表达了。
momocraft
2022-07-13 10:10:29 +08:00
显然可以有一种格式存储在二进制下无限循环的有理数

ieee754 无能为力 不是"二进制无能为力"
zmal
2022-07-13 11:01:26 +08:00
不简单不明了,解释还是错的。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/865785

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX