python中精確的浮點數運算

weapon發表於2019-02-16

起步

浮點數的一個普遍的問題是它們不能精確的表示十進位制數。

>>> a = 4.2
>>> b = 2.1
>>> a + b
6.300000000000001
>>> (a + b) == 6.3
False
>>>

這是由於底層 CPU 和 IEEE 754 標準通過自己的浮點單位去執行算術時的特徵。看似有窮的小數, 在計算機的二進位制表示裡卻是無窮的。

一般情況下,這一點點的小誤差是允許存在的。如果不能容忍這種誤差(比如金融領域),那麼就要考慮用一些途徑來解決這個問題了。

Decimal

使用這個模組不會出現任何小誤差。

>>> from decimal import Decimal
>>> a = Decimal(`4.2`)
>>> b = Decimal(`2.1`)
>>> a + b
Decimal(`6.3`)
>>> print(a + b)
6.3
>>> (a + b) == Decimal(`6.3`)
True

儘管程式碼看起來比較奇怪,使用字串來表示數字,但是 Decimal 支援所有常用的數學運算。 decimal 模組允許你控制計算的每一方面,包括數字位數和四捨五入。在這樣做之前,需要建立一個臨時上下文環境來改變這種設定:

>>> from decimal import Decimal, localcontext
>>> a = Decimal(`1.3`)
>>> b = Decimal(`1.7`)
>>> print(a / b)
0.7647058823529411764705882353
>>> with localcontext() as ctx:
...     ctx.prec = 3
...     print(a / b)
...
0.765
>>> with localcontext() as ctx:
...     ctx.prec = 50
...     print(a / b)
...
0.76470588235294117647058823529411764705882352941176
>>>

由於 Decimal 的高精度數字自然也就用字串來做展示和中轉。

總結

總的來說,當涉及金融領域時,哪怕是一點小小的誤差在計算過程中都是不允許的。因此 decimal 模組為解決這類問題提供了方法。

相關文章