isqrtのアルゴリズムの実装について
python math.isqrt
pythonのmath.isqrtは正の数nに対して、a**2がnを超えない最大の整数aを関数です。
この関数の実装が気になったので、bisectを使ったセルフ実装とpythonの実装を比べて遊んでいました。(当然ですが)math.isqrtのほうが速かったので、ソースを眺めてみました。
cpython/Modules/mathmodule.c (1555行目~)
等価な実装として、以下のurlも貼られています。
mdickinson/snippets/proofs/isqrt/src/isqrt.lean
python
1 def isqrt_aux(c, n): 2 if c == 0: 3 return 1 4 else: 5 k = (c - 1) // 2 6 a = isqrt_aux(c // 2, n >> 2*k + 2) 7 return (a << k) + (n >> k+2) // a # (A) 8 9 def isqrt(n): 10 if n == 0: 11 return 0 12 else: 13 a = isqrt_aux((n.bit_length() - 1) // 2, n) 14 return a - 1 if n < a * a else a # (B)
リンク先に証明は記述されていますが、なかなか理解には至りませんでした。
大枠としてつかんだ理解では、ビット長cの数nに対する問題を、nを(大体)ビット長の半分だけ右シフト(4^kオーダーの数を2^kオーダーに)した数に関する問題として再帰的に解くことができるということです。
ただ、コードの(A)の第一項、第二項が具体的に何を表している数なのか、(B)のチェックがなぜ必要なのかを理解できていません。
アルゴリズムに詳しい方、よろしくお願いします。
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。