如果你計算的一個Python float
x
倒數,我想不出任何理由,更喜歡x**-1.0
到1.0/x
。主觀上,我發現後者更易於閱讀。客觀地說,它可能更快(因爲它包裝了一個簡單的CPU指令,而不是對C庫的pow函數的調用),並且更準確(基於相同的原因)。
請注意,我故意用1.0
代替1
在兩個表達式,一方面是因爲避免在x
是浮動的情況了額外的int-漂浮的轉換,因爲它會保證我得到一個在x
碰巧是一個整數的情況下,在Python 2.7中使用適當的float分區而不是分區分區。
要備份「更快」的聲明,以下是我的機器上的一些定時,包括1
和1.0
的變體。這是在Python 2.7下,但在Python 3.4下的結果類似。
>>> import timeit
>>> timeit.timeit('x**-1', 'x=12.34')
0.08957314491271973
>>> timeit.timeit('x**-1.0', 'x=12.34')
0.08102011680603027
>>> timeit.timeit('1/x', 'x=12.34')
0.06166410446166992
>>> timeit.timeit('1.0/x', 'x=12.34')
0.04489898681640625
有一個相當明顯的優勢在這裏劃分形式,以及使用1.0
代替1
明顯加速。你的結果可能有所不同
注意:請勿直接插入時間表達式陷阱,如2**-1
或1.0/2.0
。這些表達式可以在編譯時通過Python的窺視優化器優化爲一個常量,這樣所有結束計時的時間就是檢索常量0.5
的時間。爲此,可以使用標準庫中的dis
模塊看到:
>>> def half_via_pow(): return 2.0**-1.0
...
>>> def half_via_div(): return 1.0/2.0
...
>>> import dis
>>> dis.dis(half_via_pow)
1 0 LOAD_CONST 3 (0.5)
3 RETURN_VALUE
>>> dis.dis(half_via_div)
1 0 LOAD_CONST 1 (1.0)
3 LOAD_CONST 2 (2.0)
6 BINARY_DIVIDE
7 RETURN_VALUE
上面顯示出關於Python 2.7,計算2.0**-1.0
被優化以恆定的,而分工1.0/2.0
不是。在Python 3.4中,兩者都被優化爲常量。我懷疑Python 2。7窺視孔優化器避免了優化分區,因此它不必擔心需要提升的情況。無論哪種方式,時間2.0**-1.0
對1.0/2.0
並沒有給出1.0/x
與x**-1.0
的速度的準確反映。時間1.0/x
而不是x**-1.0
,並在設置步驟中爲x
提供值。
對於「更準確」的聲明:1.0/x
將解析爲單個機器指令,這幾乎肯定會給你正確舍入的結果。相比之下,pow
的庫實現非常糟糕,並且經常會給出不正確舍入的結果。即使在最好的情況下,你的數學庫的pow
操作是正確舍入,它仍然不會比除法結果更準確。
作爲測試,我嘗試了下面的循環,用x ** -1.0
比較1.0/x
隨機x
值:
>>> import random
>>> while True:
... x = random.random()
... print(repr(x))
... assert 1.0/x == x**-1.0
果然,經過約200次迭代,我得到這個:
<around 200 lines of output omitted>
0.16606458447273365
0.6466363135038045
0.8650060330740814
Traceback (most recent call last):
File "<stdin>", line 4, in <module>
AssertionError
服用看看最後x
的值,我得到:
>>> x = 0.8650060330740814
>>> 1.0/x
1.1560613010364489
>>> x ** -1.0
1.1560613010364487
作爲一個粗略的檢查,它是1.0/x
在這裏正確舍入的結果,我們可以將浮點數轉換爲Fraction
(它進行確切轉換),將倒數作爲Fraction
,然後轉換回float
。 Fraction
到float
轉換是正確舍入的,並且不使用浮點運算來計算結果,所以我們不依賴於此檢查中浮點除法的精度。
>>> from fractions import Fraction
>>> float(1/Fraction(x))
1.1560613010364489
(的x
確切的倒數計算,以25個顯著數字,是1.156061301036448774438694
。我們從1.0/x
,計算出相同的精度後面的值,是1.156061301036448885071195
,而從x ** -1.0
值1.156061301036448663026590
,所以1.0/x
只是比x ** -1.0
更接近真實值,但它更接近。)
最後,在我看來最重要的是,1.0/x
更容易閱讀,並且需要較少的精力來分析。
總而言之,幾乎沒有理由選擇**
表單。
你在擔心什麼?安全?性能?精確? – CoryKramer 2014-10-03 19:09:23
@Cyber與性能或速度相比,更關心安全性和精度。 – 2014-10-03 19:19:32
您希望使用此輸入值的範圍是多少?只有'1/2'? – 2014-10-03 19:35:37