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 模組中定義的功能的使用。