python精確個數 來聊聊Python裡的「數」

2021-10-17 02:24:34 字數 2459 閱讀 3561

python中,數,用各種形式表示,不同形式的數有各自的用途。

整數整數,令人驚嘆於它的簡單。兩個整數相除,例如4/3,得到乙個浮點數,並且(4/3)*3的結果也是浮點數4.0。即便你沒有定義浮點數,在進行除法運算的時候,它會自動出現。

浮點數浮點數不是一般意義的數。按照數學上的規定,數應該遵循如下原則:減法是加法的逆運算,加法結合律,等等。

例如:>>> 1 + 2 - 2 - 1

>>> 0.1 + 0.2 - 0.2 - 0.1

2.7755575615628914e-17

兩個數相加,再分別減去它們,上述居然出現了不同的結果。

它們也不會遵循結合律:a + (b + c) = (a + b) + c

>>> a = 2**-53

>>> (a + a) + 1 == a + (a + 1)

false

以上僅僅是浮點數運算中存在的兩個「小問題」,還不令你驚訝嗎?此處不便將浮點數各種出乎意料的運算一一展現。

分數很多看似簡單的程式,遇到分數,就會出問題,比如運算時間暴增,演算法的複雜度加倍。遇到分數的時候,演算法時間不是跟輸入成正比,而是指數增長。

如果時間足夠長,記憶體爆掉也是常見的。

加法就是其中乙個典型例子

>>> print(set(type(p) for p in primes))

>>> one = fractions.fraction(1)

>>> before = datetime.now()

>>> res = sum(one/p for p in primes[:10000])

>>> after = datetime.now()

>>> print("it took", after-before)

>>> print("size of output", len(str(res)))

it took 0:01:16.033260

size of output 90676

這段程式,計算了一些素數的倒數的和。在膝上型電腦上,10000個這樣的數相加,要1分鐘,最終輸出結果的大小超過了90k。

對比著,執行浮點數運算,效能更好。

>>> print(set(type(p) for p in primes))

>>> before = datetime.now()

>>> res = sum(1/p for p in primes[:10000])

>>> after = datetime.now()

>>> print("it took", after-before)

>>> print("size of output", len(str(res)))

it took 0:00:00.000480

size of output 17

這次執行時間小於1毫秒,並且,者還可能是因為用datetime測量產生的誤差,快了10000倍。而且輸出結果的大小僅有17位元,下降了1000多倍。然而,計算結果有誤差。

誤差低於 10的-14次方,這就如同將火箭發射月球上偏差了1公釐,用浮點數計算得到的結果足夠精確,並且效率更高。

對此,一般的觀點是:python進行分數運算很慢。對此,python可以承擔10倍的責任,但不是10000倍。有乙個第三方模組,quicktions,用cython執行分數的運算。

用quicktions,真的「很快」。在我的膝上型電腦上,上面那個程式的時間,從1分16秒,縮短到1分15秒。

問題在於程式本身,在程式中,我精心選擇了一種輸入方案,以素數作為分母進行分數相加,這本來就是一種很壞的情況。

小數小數在財務中用途最廣,最無聊的是居然以法律的方式規定了小數的形式。然而,python中所有的小數點運算,都有上下文精確度問題,對此,可以用專門的模組解決。

>>> getcontext().prec = 6

>>> decimal(1) / decimal(7)

decimal('0.142857')

>>> getcontext().prec = 28

>>> decimal(1) / decimal(7)

decimal('0.1428571428571428571428571429')

在實際專案中,**中設定精度的位置和進行計算的位置可能間隔幾百行,計算可以在乙個函式中,也可以在另外乙個檔案。

最安全的方法是使用localcontext:

>>> getcontext().prec = 6

>>> # 6853 lines elided

... with localcontext() as ctx:

... ctx.prec = 10

... decimal(1) / decimal(7)

decimal('0.1428571429')

只要你認真地用localcontext,小數運算不會出問題。

總結你在程式中用到數字的時候,是否想過:應該用什麼型別?會發生什麼?誤差重要嗎?

什麼也不想,會意味著暗藏bug。

聊聊Python的time模組

time模組是很多人最早接觸到的模組,像time.sleep x 好像隨處可見,但是time模組裡面的其他方法呢?下面一起看一下time模組。1.時間戳,包括time 等函式 2.格式化的時間字元 包括asctime 等函式 3.時間元組 包括localtime 等函式 分別舉例如下 print t...

python裡 怎麼打 python裡的 怎麼輸入

python去重函式是什麼 用python寫溫度轉換 python中的 就是math.pi變數 它被包含在標準庫中,在你試圖自己計算它之前,應該先去匯入math庫,才能呼叫math.pi方法 import sys import math defmain ar if len ar 1 sys.exit...

python裝飾器 聊聊Python中的裝飾器

在django中曾經使用過 fun 這種格式的語法,用在了定義檢視的函式上,類似一種 用來控制當前檢視的訪問許可權。裝飾器 decorator 是幹嘛的?對於受到封裝的原函式來說,裝飾器能夠在那個函式執行前或者執行後分別執行一些 使得可以再裝飾器裡面訪問並修改原函式的引數以及返回值,以實現約束定義 ...