質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
アルゴリズム

アルゴリズムとは、定められた目的を達成するために、プログラムの理論的な動作を定義するものです。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

1回答

3864閲覧

isqrtのアルゴリズムについて

Ng_

総合スコア26

アルゴリズム

アルゴリズムとは、定められた目的を達成するために、プログラムの理論的な動作を定義するものです。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

2グッド

9クリップ

投稿2021/02/12 03:20

編集2021/02/12 03:26

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)のチェックがなぜ必要なのかを理解できていません。

アルゴリズムに詳しい方、よろしくお願いします。

yuwki0131, cmplstofB👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

自己解決

  • ニュートン法と関数のスケーリングで考える

wikepedia ニュートン法

関数 y = x^2 - C ... (*) を考える。
ニュートン法から、逐次的に漸近解を求めるには、
x_n+1 = x_n - f(x_n)/f'(x_n)
今考えている二次関数について、
x_n+1 = 1/2 * (x_n + C/x_n) ... (**)

ここで、小さな値についての解を計算し、それをスケールさせてもとの解を求めることを考える。
たとえば、Cを1/N倍したC/Nを例にとる。
(*)の式の辺々をNで割る。
y/N = y_ = x^2 / N + C/N
= (x/sqrt(N))^2 + C/N
= x_^2 + C/N

Cを1/Nだけスケールさせたとき、xは1/sqrt(N)だけスケールすることになる。
スケールした式でx_n+1が計算できるなら、その値をsqrt(N)倍すれば欲しい解が求まるはずである。

sqrtの計算に都合のいいように、Cを1/2^(2k + 2)だけスケールさせる(これは2K+2だけ右シフトすることと同じ)。Xは2^-(k + 1)だけスケールする。スケールした先で求まった漸近解をaとすると、(**)は、
x_n+1 = 1/2 * (a + (C >> 2*k + 2)/a)
x_n+1をもとのスケールに戻すには、2^(k+1)だけもどしてやればいいので、
1/2の係数を考慮して一項目のaはkだけ左シフト、二項目はk + 2だけ左シフトすればいい。

最後に、Cが平方数であるかどうかをチェックして、そうでなければ-1した値が条件を満たす最大のということになる。

投稿2021/02/13 01:21

Ng_

総合スコア26

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問