请选择 进入手机版|继续访问电脑版
发新帖

Python 浮点的坑 怎么完美避免?

[复制链接]
6661 22

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有帐号?立即注册

x

                               
登录/注册后可看大图



万万没想到
自己用 round 还是有坑

                               
登录/注册后可看大图


新上手 python,打算跑脚本对账用的,可这坑太大了吧

之前是写 php 的没遇到过这个问题,查了一下都说是进制的问题道理我是懂了,可是日常怎么避坑比较完美?请各位大佬指教。

举报 使用道具

回复

精彩评论22

serho  新手上路  发表于 2018-4-3 13:01:20 | 显示全部楼层
1. 用 decimal

>  from decimal import *
>  getcontext().rounding = ROUND_HALF_UP
> Decimal("7.2") * Decimal("9.3")
Out[3]: Decimal('66.96')
> Decimal("0.1") + Decimal("0.1") + Decimal("0.1")
Out[4]: Decimal('0.3')
> Decimal("2.675").quantize(Decimal("0.00"))
Out[5]: Decimal('2.68')

2. 用分作为单位使用整数

举报 使用道具

回复
xivn1987  新手上路  发表于 2018-4-3 13:06:49 | 显示全部楼层
别用 float,,用 decimal

举报 使用道具

回复
blankme  新手上路  发表于 2018-4-3 13:07:27 | 显示全部楼层
乘以 100,用 int

举报 使用道具

回复
luckyray  新手上路  发表于 2018-4-3 13:12:00 | 显示全部楼层
楼上说的对,升几位用整数

举报 使用道具

回复
qingmumu  新手上路  发表于 2018-4-3 13:12:39 | 显示全部楼层
@SErHo #1
@XIVN1987
@blankme #3
@Luckyray #4
感谢各位已决定用 decimal

举报 使用道具

回复
d3ep  新手上路  发表于 2018-4-3 13:13:39 | 显示全部楼层
PHP 没有这种情况?都是 IEE754 怎么可能没有。

举报 使用道具

回复
qingmumu  新手上路  发表于 2018-4-3 13:23:55 | 显示全部楼层
@D3EP #6  

                               
登录/注册后可看大图
  可能学艺不精,但是 php 里没踩到这个坑,至少以上情况 php 正常

举报 使用道具

回复
akira  新手上路  发表于 2018-4-3 13:32:04 | 显示全部楼层
大部分语言的浮点数都有同样或类似的问题,特别是编译型语言。 根源是浮点数在计算机中的存储格式。
方案的话,上面说的基本上就是了

举报 使用道具

回复
xpresslink  新手上路  发表于 2018-4-3 13:36:40 | 显示全部楼层
楼主认为这个是 python 的坑说明基础知识太差。
所有编程语言都有这个问题,这个是计算机体系结构本身制约造成的。
浮点数运算的结果经常会出现无限循环或无限不循环小数,计算机只能用有限位来近似表示。

举报 使用道具

回复
ipwx  新手上路  发表于 2018-4-3 13:38:25 | 显示全部楼层
别的语言也是一样的,只不过他们输出的时候没输出这么多位而已。

任何浮点数,只要小数部分不能写成 2 的负整数次幂的和,就有误差。

比如 0.25 = 2^{-2},所以是精确的。但是 0.1 无法写成任何 2 的负整数次幂,所以会有误差。

举报 使用道具

回复
zhicheng  新手上路  发表于 2018-4-3 13:46:06 | 显示全部楼层
一般应用不必用 decimal,因为无限不循环小数的存在的所以现在的计算机架构无法完美表示浮点数。你用的任何方式都是一定条件的取舍。

举报 使用道具

回复
joeke  新手上路  发表于 2018-4-3 13:47:10 | 显示全部楼层
php 也是一样的

举报 使用道具

回复
ipwx  新手上路  发表于 2018-4-3 13:52:08 | 显示全部楼层
@zhicheng “对账用”

举报 使用道具

回复
xpresslink  新手上路  发表于 2018-4-3 13:53:50 | 显示全部楼层
@qingmumu 在 python2.x 里 decimal 性能比浮点数低 1000 倍。
python3.x 里 decimal 被改用 C 语言实现了性能要好一些。
所有还要看你对性能是不是敏感。

举报 使用道具

回复
wizardoz  新手上路  发表于 2018-4-3 13:59:37 | 显示全部楼层
这是 float 的存储格式决定的,大部分语言的 float 存储格式都是这样的。
从根源上来说,是二进制数据表示浮点数必然会丢失精度的问题。

举报 使用道具

回复
pcar  新手上路  发表于 2018-4-3 14:37:45 | 显示全部楼层
*100

举报 使用道具

回复
araraloren  新手上路  发表于 2018-4-3 14:56:36 | 显示全部楼层
Perl6 not have this problem:

say 0.88882 - 0.22335 == 0.66547;  # True

[Try it online!]( https://tio.run/##K0gtyjH7/784sVLBQM8CCIwUdIEsIyNjY1MFW1sg08zM1MTc@v9/AA "Perl 6 – Try It Online")

举报 使用道具

回复
tonghuashuai  新手上路  发表于 2018-4-3 15:18:00 | 显示全部楼层
记住一句话:涉及到钱的问题,一律用 decimal

举报 使用道具

回复
qingmumu  新手上路  发表于 2018-4-3 15:22:04 | 显示全部楼层
确实基础差

举报 使用道具

回复
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表