11

「 Pythonプログラミング:コンピュータサイエンス入門」からの引用

べき乗**を使用して平方根を取ることができます。math.sqrtを使用すると、いくらか効率的です。

「やや」ですが、どの程度、どのように?

4

5 に答える 5

16

理論的には、hammarの答えduffymoの答えは良い推測です。しかし実際には、私のマシンでは、それより効率的ではありません。

>>> import timeit
>>> timeit.timeit(stmt='[n ** 0.5 for n in range(100)]', setup='import math', number=10000)
0.15518403053283691
>>> timeit.timeit(stmt='[math.sqrt(n) for n in range(100)]', setup='import math', number=10000)
0.17707490921020508

問題の一部は.操作です。sqrt名前空間に直接インポートすると、わずかに改善されます。

>>> timeit.timeit(stmt='[sqrt(n) for n in range(100)]', setup='from math import sqrt', number=10000)
0.15312695503234863

そこのキーワード:わずか

さらなるテストは、数が大きくなるにつれて、使用することから得られる利益がsqrt増加することを示しています。しかし、それでもそれほど多くはありません!

>>> timeit.timeit(stmt='[n ** 0.5 for n in range(1000000)]', setup='import math', number=1)
0.18888211250305176
>>> timeit.timeit(stmt='[math.sqrt(n) for n in range(1000000)]', setup='import math', number=1)
0.18425297737121582
>>> timeit.timeit(stmt='[sqrt(n) for n in range(1000000)]', setup='from math import sqrt', number=1)
0.1571958065032959
于 2011-07-09T21:35:24.343 に答える
11

実装を推測する必要はありません。コードを読むことができます。

math.sqrtsqrt標準Cライブラリの薄いラッパーですmathmodule.c。956行を参照してください。

演算子には、引数のタイプに応じて複数の**実装がありますが、浮動小数点指数の場合、最終的にpowは標準Cライブラリからディスパッチします(floatobject.c783行目を参照)。

最近のCPUには、一般的なべき乗ルーチンでは使用されない特別な平方根命令が含まれていることがよくあります(たとえば、x86-64のglibcの実装との実装を比較対照します)powsqrtただし、すべてのインタープリターオーバーヘッド(バイトコード、タイプチェック、メソッドディスパッチなど)が追加されると、生の速度の違いはそれほど重要ではなく、sqrt直接呼び出すか、mathモジュール(他の回答のタイミングで示されているように)。

于 2011-07-09T22:28:05.867 に答える
1

**math.sqrt常にであることを知っている間、指数をサポートする必要があり0.5ます。math.sqrtしたがって、より特殊な(したがっておそらくより効率的な)アルゴリズムを使用できます。

于 2011-07-09T21:33:50.760 に答える
1

私の推測では、math.sqrtは2乗に収束するニュートン法を使用し、べき乗はより遅い他の方法を使用します。

于 2011-07-09T21:35:50.513 に答える
1

これは少し異なるアプローチです。平方根より少し大きいintが必要です。2つの方法(平方数には同意しませんが、それで問題ありません):

>>>timeit.timeit(stmt='[int(n**0.5)+1 for n in range(1000000)]', setup='', number=1)  
0.481772899628  
>>>timeit.timeit(stmt='[ceil(sqrt(n)) for n in range(1000000)]', setup='from math import sqrt, ceil', number=1)  
0.293844938278  
>>>timeit.timeit(stmt='[int(ceil(sqrt(n))) for n in range(1000000)]', setup='from math import sqrt, ceil', number=1)  
0.511347055435

したがって、数学関数はより高速です...floatをintに変換するまで。(値と多くの比較を行う必要があります。テストはしていませんが、整数の比較は浮動小数点数の比較よりも安価であるはずです。)

しかしねえ、それはPythonです。このレベルの粒度でパフォーマンスを最適化しようとするには、抽象化が多すぎます。

于 2011-12-18T18:13:40.767 に答える