Decimal 是 Python 中好用的處理精確浮點數模組,但在某些情況下會發生 InvalidOperation,這邊分享遇到的原因以及解決方式。
問題如何發生?
在 python 下,嘗試建立一個很大的 Decimal 數值 5 * 10^31,然後對他做 quantize (也就是 decimal 的 round)到小數第二位,就會發生 Invalid Operation
>>> from decimal import Decimal
>>> d = Decimal('5.00E+31')
>>> d.quantize(Decimal('0.01'))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
decimal.InvalidOperation: [<class 'decimal.InvalidOperation'>]
為何發生 InvalidOperation?
主因是系統精度不夠造成,可以用以下指令確認目前最大精度
>>> from decimal import getcontext
>>> getcontext()
Context(prec=28, rounding=ROUND_HALF_EVEN, Emin=-999999, Emax=999999, capitals=1, clamp=0, flags=[InvalidOperation], traps=[InvalidOperation, DivisionByZero, Overflow])
目前系統精度是 28,若要讓輸入的 32 位數值能夠 round 到小數第 2 位,總共需要 32 + 2 = 34 位的精度,超過系統上限所以 raise InvalidOperation
quantize 時給定足夠的精度
在 quantize 時動態給定夠大的精度即可解決,詳細如下
>>> from decimal import Context
>>> d.quantize(Decimal('0.01'), context=Context(prec=34))
Decimal('50000000000000000000000000000000.00')
如果覺得我文章內容對你有幫助的話,請在文章後面幫我按 5 個讚!讓我知道大家都喜歡什麼內容哦!
範例原始碼在此下載:github
延伸閱讀:
Python 詭譎的 default parameter value ,由踩坑來學習!
被新創公司裁員後,我學到的五件事
參考資料:
Decimal.quantize raises InvalidOperation
Decimal fixed point and floating point arithmetic