Python中的十進位制定點和浮點運算


浮點數在記憶體中以2為基數的二進位制分數表示。因此,浮點運算有時會很奇怪。0.1和0.2的加法可能會產生令人煩惱的結果,如下所示:

>>> 0.1 + 0.2
0.30000000000000004

事實上,這是二進位制浮點表示的本質。這在任何程式語言中都很普遍。Python 提供了一個 decimal 模組來執行快速且正確舍入的浮點運算。

decimal 模組旨在精確地表示浮點數,就像人們希望它們的行為一樣,並且算術運算的結果與預期一致。表示和運算的精度級別可以設定為最多 28 位。

decimal 模組定義了 Decimal 類。Decimal 物件可以透過給其建構函式提供整數、帶有數字表示的字串或元組作為引數來宣告。

>>> from decimal import Decimal
>>> d1 = Decimal(10)
>>> d1
Decimal('10')
>>> d2 = Decimal('10')
>>> d2
Decimal('10')

元組引數包含三個元素:符號(正數為 0,負數為 1)、數字元組和指數。例如:

>>> d3 = Decimal((1, (1, 2,3, 4), 2))
>>> d3
Decimal('-1.234E+5')

表示特定精度浮點數的一種更便捷的方法是透過 getcontext() 函式獲取當前執行緒的上下文環境,併為 Decimal 物件設定精度。

>>> from decimal import Decimal, getcontext
>>> getcontext().prec = 5
>>> d3 = Decimal(10)
>>> d4 = Decimal(3)
>>> d3/d4
Decimal('3.3333')

上下文是用於算術運算的環境,用於確定精度和定義舍入規則,以及限制指數範圍。

decimal.getcontext() − 返回活動執行緒的當前上下文。

decimal.setcontext(c) − 將活動執行緒的當前上下文設定為 c。

decimal 模組中定義了以下舍入模式常量:

ROUND_CEILING向無窮大舍入。
ROUND_DOWN向零舍入。
ROUND_FLOOR向 -無窮大舍入。
ROUND_HALF_DOWN最接近的舍入,如果相等則向零舍入。
ROUND_HALF_EVEN最接近的舍入,如果相等則向最近的偶數整數舍入。
ROUND_HALF_UP最接近的舍入,如果相等則遠離零舍入。
ROUND_UP遠離零舍入。
ROUND_05UP如果向零舍入後的最後一位數字為 0 或 5,則遠離零舍入;否則向零舍入。

以下程式碼片段使用上下文物件的精度和舍入引數。

>>> from decimal import *
>>> getcontext().prec = 5
>>> getcontext().rounding = ROUND_UP
>>> d1 = Decimal(100)
>>> d2 = Decimal(6)
>>> d1/d2
Decimal('16.667')

Decimal 物件的算術運算

所有常用的算術運算都可以在 Decimal 物件上進行,就像普通的浮點數一樣。

>>> a = Decimal('2.4')
>>> b = Decimal('1.2')
>>> a + b
Decimal('3.6')
>>> a - b
Decimal('1.2')
>>> b - a
Decimal('-1.2')
>>> a * b
Decimal('2.88')
>>> a / b
Decimal('2')

算術運算可以在一個 Decimal 運算元和一個整數運算元上進行。但是,對於普通的浮點物件,操作是無效的。

>>> a = Decimal('2.4')
>>> c = 2.1
>>> a + c
Traceback (most recent call last):
File "<pyshell#37>", line 1, in <module>
a+c
TypeError: unsupported operand type(s) for +: 'decimal.Decimal' and 'float'

所有算術運算都會發生相同的異常。

餘數 (%) 運算子與 Decimal 物件的行為與普通數字型別略有不同。在這裡,結果的符號是被除數的符號,而不是除數的符號。

>>> -7%3
2
>>> 7%-3
-2
>>> Decimal(-7) % Decimal(3)
Decimal('-1')
>>> Decimal(7) % Decimal(-3)
Decimal('1')

Decimal.from_float() − 此函式將普通浮點數轉換為具有精確二進位制表示的 Decimal 物件。因此,from_float(0.1) 和 Decimal('0.1') 不相同。

>>> d1 = Decimal('0.1')
>>> d2 = Decimal.from_float(0.1)
>>> d1,d2
(Decimal('0.1'), Decimal('0.1000000000000000055511151231257827021181583404541015625'))

本文解釋了 Python 標準庫的 decimal 模組中定義的功能的使用。

更新於:2019年7月30日

瀏覽量 1K+

啟動您的 職業生涯

透過完成課程獲得認證

開始學習
廣告