python的数字比较好_说说 Python3 中的数字处理
最近在處理訂單相關(guān)的問(wèn)題,踩了數(shù)字的一些坑,在此記錄下。
其中有問(wèn)題的代碼涉及金額比較,便于描述,假設(shè)了下面一段代碼
def is_paid(pay_price, paid_price):
return pay_price == paid_price
# 數(shù)據(jù)表中的記錄類(lèi)似這樣
# id pay_price ...
# 1 12.3
# ...
# 操作如下
# 這里使用了 SQLAlchemy 的 ORM 形式讀取數(shù)據(jù)
order = Order.query.filter_by(id=1).first()
if is_paid(order.pay_price, 12.3):
print('paid')
else:
print('unpaid')
# 最后打印的卻是 unpaid
跟蹤代碼才發(fā)現(xiàn) order.pay_price 是 Decimal 類(lèi)型,而 12.3 是浮點(diǎn)類(lèi)型,Python 是強(qiáng)類(lèi)型語(yǔ)言,類(lèi)型不一樣當(dāng)然不等。
>>> from decimal import Decimal as d
>>> a = d('12.3')
>>> b = 12.3
>>> type(a)
>>> type(b)
>>> a
Decimal('12.3')
>>> b
12.3
>>> a == b
False
仔細(xì)想想,有點(diǎn)不對(duì),你看 1 == 1.0 就成立啊,不也是不同類(lèi)型(整型和浮點(diǎn)型)嗎。
不管是不是強(qiáng)類(lèi)型語(yǔ)言,數(shù)字之間作比較還是應(yīng)該要能行的吧。
這里沒(méi)有深挖,感覺(jué)就是 Python 設(shè)計(jì)的緣故吧。
所以,這里應(yīng)該怎么作等值比較,試了下 math.isclose(a, b) ,嗯,行得通。
本應(yīng)該在這里結(jié)束了,但,不小心玩了下
>>> m = 0.1 + 0.2
>>> n = 0.3
>>> m == n
False
納尼
然后打印了下值
>>> m
0.30000000000000004
>>> n
0.3
我還有什么話可說(shuō)呢,這下讓我對(duì) Python 浮點(diǎn)數(shù)的處理產(chǎn)生了懷疑。
也讓自己對(duì)以前所寫(xiě)的數(shù)字比較產(chǎn)生了懷疑,天哪,全是 Bug 。不過(guò)后面想通了,不存在的 :)
>>> x = 1.0
>>> y = Decimal('2')
>>> x + y
Traceback (most recent call last):
File "", line 1, in
TypeError: unsupported operand type(s) for +: 'float' and 'decimal.Decimal'
這下,搞得我以后都不知道怎么處理數(shù)字了。程序中很多地方都沒(méi)判斷類(lèi)型,呀,又是一堆隱患。(同樣,還是想多了...)
為了理清自己的思路,又試了下
>>> z = 3
>>> y + 3
Decimal('5')
原來(lái),Decimal 和整型是能進(jìn)行算術(shù)運(yùn)算的。
后面自己冷靜了下,終于想通了。
程序中,我們用的很多庫(kù),涉及小數(shù)的基本上都是用的 Decimal 類(lèi)型,比如 SQLAchemy ORM 取出來(lái)的小數(shù)數(shù)據(jù)都是此類(lèi)型。
Decimal 之間比較一般精度的數(shù)字都是沒(méi)問(wèn)題的,并且程序中我們定義數(shù)字的初始值基本都是整型 0 ,和 Deciamal 運(yùn)算沒(méi)有問(wèn)題,所以上面的疑慮都煙消云散了。
所以,在以后的數(shù)字處理中,自己盡量只使用整型和 Decimal 類(lèi)型,來(lái)避免上面的隱形問(wèn)題。
不過(guò),要注意
>>> t1 = Decimal(0.123)
>>> t2 = Deciaml('0.123')
>>> t1 == t2
False
這是由于浮點(diǎn)數(shù) 0.123 在轉(zhuǎn)為 Decimal 的時(shí)候失去了精度
>>> t1
Decimal('0.1229999999999999982236431605997495353221893310546875')
>>> t2
Decimal('0.123')
因此,定義 Decimal 類(lèi)型的時(shí)候,我們盡量使用字符串來(lái)避免這個(gè)問(wèn)題。
本文首發(fā)于公眾號(hào)「小小后端」,關(guān)注并回復(fù)「1024」有驚喜哦。
總結(jié)
以上是生活随笔為你收集整理的python的数字比较好_说说 Python3 中的数字处理的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: vue双击事件_我总结了12个Vue.j
- 下一篇: python的常用数据类型_python