为什么很多编程语言都采用IEEE754格式编码数字,然后就产生0.1+0.2 != 0.3这样的事情,没有更合理的吗?

2013-06-08 17:47:49 +08:00
 CoooolChan
5120 次点击
所在节点    问与答
20 条回复
wy315700
2013-06-08 18:11:36 +08:00
float型的一般不直接比较 都是用的 abs((0.1+0.2) - 0.3) <= inf 做比较的
clowwindy
2013-06-08 18:39:32 +08:00
让我想起了用 Quartz 想顺时针画一个 2pi 的圆,会什么也画不出来。

苹果文档:

Note that using values very near 2π can be problematic. For example,
setting `startAngle' to 0, `endAngle' to 2π, and `clockwise' to true will
draw nothing. (It's easy to see this by considering, instead of 0 and 2π,
the values ε and 2π - ε, where ε is very small.) Due to round-off error,
however, it's possible that passing the value `2 * M_PI' to approximate
2π will numerically equal to 2π + δ, for some small δ; this will cause a
full circle to be drawn.

If you want a full circle to be drawn clockwise, you should set
`startAngle' to 2π, `endAngle' to 0, and `clockwise' to true. This avoids
the instability problems discussed above.
hadoop
2013-06-08 19:34:54 +08:00
数学上的小数点后面可以有成千上万位,但是计算机无法有效的用二进制表示
luikore
2013-06-08 20:27:35 +08:00
0.3 和 0.299999 哪个更精确? 上过高中都知道是后者
CoooolChan
2013-06-08 21:22:28 +08:00
@luikore 那1和0.99999999999还相等呢
013231
2013-06-08 21:30:02 +08:00
有限長度的字節可表示的狀態是有限的, 實數的數量是無限的, 無論你怎麼設計數字編碼方案, 總有無窮多個數無法表示.
iloahz
2013-06-08 23:39:16 +08:00
@wy315700 inf -> eps?
chon
2013-06-08 23:48:23 +08:00
因为不是所有的数字都能用二进制表示
因此用二进制表示,不惯是什么编码方案,都不能做到非常精确
csx163
2013-06-08 23:53:06 +08:00
最讨厌浮点了(游戏作弊方面)
wy315700
2013-06-09 15:01:07 +08:00
@iloahz 好吧 好久没写了 都忘了
rrfeng
2013-06-09 16:53:57 +08:00
引申一下:
有没有可能建立完全精确的实数运算器?及其相应的算法?
luikore
2013-06-09 17:12:35 +08:00
@rrfeng 不可能, 宇宙有限, 实数无限
skydiver
2013-06-09 17:18:01 +08:00
当然可以了,那些科学计算软件计算的肯定是精确值啊。。

只不过计算机浮点指令就是按照这种标准制定的,所以直接这么存储可以直接用浮点指令。如果想要精确的结果只能用间接的方法了,效率会降低。
RisingV
2013-06-09 17:26:16 +08:00
现有存储介质都是2进制。
2进制的进制基数是2,那么一个数字只要被因素包含大于2的质数的数除,都会产生无限循环小数。

无限循环小数和无理数都无法,和非无限循环的有理数一起用同一种方式存储到存储介质上的同时
还保持计算的兼容性。

对于无限循环小数,可以设计一种格式存储到介质上,但是同时又要和非无限循环的有理数能够计算,效率应该会变得非常低下。

对于无理数,小数位的数字没有规律可循,所以根本无法保存精确值,只能保存近似值。

高精度计算,一般可以将数字转发成string, 去掉小数点,按位计算再保存回string,再加回小数点。
rrfeng
2013-06-09 17:28:01 +08:00
@luikore
python 不是新增了 [实数] 表示么

我觉得是可以的,以现在的硬件,模仿手工算法来进行计算
至少有理数完全可以实现吧,设计分数运算规则和存储规则即可。

无理数不好确定……
davepkxxx
2013-06-09 17:51:52 +08:00
各个语言对于浮点类型数据的比较一般都会有个允许偏差的范围。
davepkxxx
2013-06-09 17:52:44 +08:00
我遇到过最厉害的还是有部分语言不支持浮点类型。
luikore
2013-06-09 18:04:50 +08:00
@rrfeng 你说的是十进制表示而不是无限精确计算, 例如 √2 是不可能用十进制小数精确表示的
est
2013-06-09 18:41:10 +08:00
每个语言都支持 IEEE754 的原因是:现代CPU的FPU都是基于IEEE754。

你用算数方法去精确n位的计算也可以,但是硬件FPU效率可以秒杀你一条银河系。

如果实在有精确浮点的需要,可以使用一些软浮点大数库。
rrfeng
2013-06-10 06:32:03 +08:00
@luikore
想了一下,我原来的期望是,运算过程不损失精度,得到一个特定的表示方式的结果,然后取值的时候只要进行一种/一次 会丢失精度的运算过程,而且可以方便的获得任意精度的最终结果。

比如有理数运算,完全可以基于分数表示法和分数运算法则,最后得到一个分数。这个是精确的,我们要取值的时候,只要做一次除法运算,就可以了

但实际上除法运算不是基本运算……呃 无解么

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

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

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

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

© 2021 V2EX