[解決済み] なぜ pow(a, d, n) は a**d % n よりも速いのですか?
2022-09-08 03:20:27
質問
を実装しようとしていたのですが ミラー・ラビン一次性検定 を実装しようとしていたのですが、中程度の数 (~7 digits) でなぜこんなに時間がかかるのか (> 20 seconds) 困惑していました。最終的に、次のコードの行が問題の原因であることを発見しました。
x = a**d % n
(ここで
a
,
d
そして
n
はいずれも似て非なる中型の数字である。
**
は指数演算子、そして
%
はモジュロ演算子)
次に私は、以下のように置き換えてみました。
x = pow(a, d, n)
であり、それに比べればほとんど瞬時である。
文脈上、元の関数は以下の通りです。
from random import randint
def primalityTest(n, k):
if n < 2:
return False
if n % 2 == 0:
return False
s = 0
d = n - 1
while d % 2 == 0:
s += 1
d >>= 1
for i in range(k):
rand = randint(2, n - 2)
x = rand**d % n # offending line
if x == 1 or x == n - 1:
continue
for r in range(s):
toReturn = True
x = pow(x, 2, n)
if x == 1:
return False
if x == n - 1:
toReturn = False
break
if toReturn:
return False
return True
print(primalityTest(2700643,1))
時限計算の例です。
from timeit import timeit
a = 2505626
d = 1520321
n = 2700643
def testA():
print(a**d % n)
def testB():
print(pow(a, d, n))
print("time: %(time)fs" % {"time":timeit("testA()", setup="from __main__ import testA", number=1)})
print("time: %(time)fs" % {"time":timeit("testB()", setup="from __main__ import testB", number=1)})
出力(PyPy 1.9.0での実行)。
2642565
time: 23.785543s
2642565
time: 0.000030s
出力 (Python 3.3.0 で実行、2.7.2 は非常に似た時間を返します)。
2642565
time: 14.426975s
2642565
time: 0.000021s
そして関連する質問ですが、なぜこの計算をPython 2や3で実行すると、PyPyで実行するよりも2倍近く速くなるのか、通常PyPyでは より速い ?
どのように解決するのですか?
Wikipedia の
モジュール式指数関数
. 基本的には
a**d % n
を計算する必要があります。
a**d
を計算しなければならず、これはかなり大きくなる可能性がある。 しかし
a**d % n
を計算することなく
a**d
を計算することなく、その分
pow
が行うものです。 その
**
演算子は、すぐにモジュラスを取ろうとしていることを知るために、未来を見通すことができないので、これを行うことはできません。
関連
-
[解決済み] B "の印刷が "#"の印刷より劇的に遅いのはなぜですか?
-
[解決済み] Python 3で「1000000000000000 in range(1000000000000001)」はなぜ速いのですか?
-
[解決済み] 要素ごとの加算は、結合ループよりも分離ループの方がはるかに高速なのはなぜですか?
-
[解決済み] なぜC++はPythonよりもstdinからの行の読み込みが遅いのですか?
-
[解決済み] <は<=より速いのか?
-
[解決済み] なぜJavaでは2 * (i * i)の方が2 * i * iより速いのですか?
-
[解決済み] なぜ[]はlist()よりも速いのですか?
-
[解決済み】PyPyが6.3倍速いなら、CPythonよりPyPyを使うべきじゃないのか?
-
[解決済み] Pythonです。未束縛のメソッドを束縛する?
-
[解決済み] あるオブジェクトが数であるかどうかを確認する、最もパイソン的な方法は何でしょうか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] 辞書のキーと値を交換するにはどうすればよいですか?
-
[解決済み] なぜ(0-6)は-6=偽なのか?重複
-
[解決済み] python-requests モジュールからのすべてのリクエストをログに記録します。
-
[解決済み] 範囲指定された浮動小数点数のランダムな配列を生成します。
-
[解決済み] サブフォルダからのインポートモジュール
-
[解決済み] Cythonのコードを含むPythonパッケージはどのように構成すればよいのでしょうか?
-
[解決済み] Pythonによる一対のクロスプロダクト [重複] (英語)
-
[解決済み] virtualenv の `--no-site-packages` オプションを元に戻す。
-
[解決済み] Pythonの検索パスを他のソースに展開する
-
[解決済み] 単純な文字列からtimedeltaオブジェクトを作成する方法