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

2018-04-01 15:04:31 +08:00
 qingmumu



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


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

之前是写 php 的没遇到过这个问题,查了一下都说是进制的问题道理我是懂了,可是日常怎么避坑比较完美?请各位大佬指教。
4076 次点击
所在节点    Python
20 条回复
SErHo
2018-04-01 15:32:38 +08:00
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-04-01 15:33:34 +08:00
别用 float,,用 decimal
blankme
2018-04-01 15:35:10 +08:00
乘以 100,用 int
Luckyray
2018-04-01 15:38:08 +08:00
楼上说的对,升几位用整数
qingmumu
2018-04-01 15:53:53 +08:00
@SErHo #1
@XIVN1987
@blankme #3
@Luckyray #4
感谢各位已决定用 decimal
D3EP
2018-04-01 15:59:33 +08:00
PHP 没有这种情况?都是 IEE754 怎么可能没有。
qingmumu
2018-04-01 16:04:27 +08:00
@D3EP #6 可能学艺不精,但是 php 里没踩到这个坑,至少以上情况 php 正常
akira
2018-04-01 16:17:55 +08:00
大部分语言的浮点数都有同样或类似的问题,特别是编译型语言。 根源是浮点数在计算机中的存储格式。
方案的话,上面说的基本上就是了
xpresslink
2018-04-01 16:27:53 +08:00
楼主认为这个是 python 的坑说明基础知识太差。
所有编程语言都有这个问题,这个是计算机体系结构本身制约造成的。
浮点数运算的结果经常会出现无限循环或无限不循环小数,计算机只能用有限位来近似表示。
ipwx
2018-04-01 16:46:05 +08:00
别的语言也是一样的,只不过他们输出的时候没输出这么多位而已。

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

比如 0.25 = 2^{-2},所以是精确的。但是 0.1 无法写成任何 2 的负整数次幂,所以会有误差。
zhicheng
2018-04-01 17:13:00 +08:00
一般应用不必用 decimal,因为无限不循环小数的存在的所以现在的计算机架构无法完美表示浮点数。你用的任何方式都是一定条件的取舍。
joeke
2018-04-01 18:02:36 +08:00
php 也是一样的
ipwx
2018-04-01 20:37:45 +08:00
@zhicheng “对账用”
xpresslink
2018-04-02 10:16:09 +08:00
@qingmumu 在 python2.x 里 decimal 性能比浮点数低 1000 倍。
python3.x 里 decimal 被改用 C 语言实现了性能要好一些。
所有还要看你对性能是不是敏感。
wizardoz
2018-04-02 10:36:01 +08:00
这是 float 的存储格式决定的,大部分语言的 float 存储格式都是这样的。
从根源上来说,是二进制数据表示浮点数必然会丢失精度的问题。
pcar
2018-04-02 13:06:05 +08:00
*100
araraloren
2018-04-02 16:30:49 +08:00
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-04-02 17:31:52 +08:00
记住一句话:涉及到钱的问题,一律用 decimal
qingmumu
2018-04-02 17:45:18 +08:00
确实基础差😂
qingmumu
2018-04-02 17:45:50 +08:00
@xpresslink 确实基础差 要努力了

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

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

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

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

© 2021 V2EX