任意精度の整数平方根アルゴリズム?


9

nビット整数の平方根のフロアを計算するための既知のサブ二次アルゴリズムはありますか?

素朴なアルゴリズムは次のようなものです

def sqrt(x):
    r = 0
    i = x.bit_length() // 2
    while i >= 0:
        inc = (r << (i+1)) + (1 << (i*2))
        if inc <= x:
            x -= inc
            r += 1 << i
        i -= 1
    return r

これにはO(n)反復が必要であり、各反復にはO(n)時間である加算が含まれるため、O(n^2)全体として時間です。もっと速いものはありますか?乗算の場合、2次時間よりも優れた特別なアルゴリズムがあることは知っていますが、平方根については何も見つかりません。


関連するものに対する私の答えはcs.stackexchange.com/a/37338/12052を助けるかもしれません。唯一の問題は、その精度を微調整するために経験的に見つけなければならない必要な方程式の一部です。
Francesco Gramano

@FrancescoGramano:すみません、それは役に立たないと思います。
Aryabhata

ところで、この準二次要件はより大きな問題の一部ですか?単純な二次と複雑な二次の違いは、実際にはそれほど大きくない可能性があるためです。それとも理論的に興味があるだけですか?
Aryabhata 2015年

@Aryabhata申し訳ありませんが、以前にあなたのコメントを見ていません。いいえ、それはより大きな問題の一部ではなく、単に好奇心です。
アンチモン2015年

回答:


5

多項式p x = x 2cの根への近似を見つけるために、ニュートン法または他の多くの方法のいずれかを使用できます。p(x)=x2c

ニュートン法の収束率は2次式になります。つまり、正しいビット数が各反復で2倍になります。これは、ニュートン法の回の反復で十分であることを意味します。O(lgn)

ニュートン法の各反復は

バツj+1=バツjバツj2c/2バツj=0.5バツj+c2バツj

乗算のビット複雑度はOb lg b )で、2つのbビット整数を乗算します(lg lg b係数を無視)。(bビットの精度への)除算のビット複雑度は同じです。したがって、各反復はOn lg n 演算で計算できます。O lg n )の繰り返しを掛けると、平方根をnビットの精度で計算する全体の実行時間はOn lg n)になります。O blgbblglgbbO (nlgn)O(lgn)n。これは準二次式です。O (n(lgn)2)

私はこれがに向上させることができる、より慎重な分析が示すと考えるOnはLG N (我々は唯一の各知っておく必要があることを考慮することで、時間を実行しているが、Xのjはおよそ内にj個の精度のビットではなく、nは精度のビット) 。ただし、より基本的な分析でも、実行時間は明らかに2次以下です。O (nlgn)xjjn


バイナリ1も同一用いて大きな初期推定有し。ログを計算する代わりに、xの桁数としてlog 2 xを概算できます。例えば、ログ2 101011 6x1/2=21/2log2xlog2xxlog21010116
Nick Alger、2015年

@DW:しかし、整数平方根を探していませんか?整数演算のみを使用してニュートン法の反復を行う場合は、クレームを正当化する必要がありますね。それ以外の場合は、すでに十分に大きな精度を想定しています...明らかなものがない場合は申し訳ありません。O(logn)
Aryabhata 2015年

@DW: 「ニュートン法の収束率」は、cの場合、2次式にはなりません。、そして私は非負の実数ではない cの値に対して何が起こるかわかりません。c=0c乗算のビットの複雑さの見積もりは、次の備考が示唆するよりも厳しいですまた、「各を約内に知る必要がある」2xj「精度のビット」。2j

@Aryabhata: 「整数平方根を探している」わけではありません。「平方根の床」を探しています。 同じビットの複雑さは浮動小数点演算にも当てはまりますが、整数演算の問題についてはあなたは正しいです。

1
@RickyDemer、はい、は特殊なケースです。これは、p x )の根が多重度2を持っているためです。ただし、c > 0のとき、根は多重度1を持っているため、ニュートン法 2次収束します。ニュートンの方法を使用してc = 0の平方根を計算する人はいないと思います(ゼロの平方根は明らかにゼロであるため)。それで、あなたは何を言おうとしているのですか?あなたのコメントは、私の答えに「特別な場合はゼロの平方根」を追加することで対処される簡単なコメントですか、それとも私が欠けているもっと深い何かがありますか?c=0p(x)c>0c=0
DW

6

ニュートン法の問題の1つは、反復ごとに除算演算が必要になることです。これは、最も遅い基本的な整数演算です。

しかし、平方根に対するニュートンの方法はそうではありません。が検索したい番号の場合1x、繰り返し:1x

ri+1=12ri(3xri2)

これはしばしば次のように表現されます:

d i = 1 w i x r i + 1 = r i + r i d i

wi=ri2
di=1wix
ri+1=ri+ridi2

これが3つの乗算演算です。2による除算は、右シフトとして実装できます。

ここで問題は、が整数ではないことです。ただし、浮動小数点を手動で実装し、必要に応じて一連のシフト操作を実行して補正することで、そのように操作できます。r

まず、再スケーリングします。x

x=22ex

ここで、1より大きく、ただし1に近くしたいとします。私たちは、上記のアルゴリズムを実行した場合のx "の代わりに、Xを、我々は見つけるR = 1をx1xx。次に、r=1xx=2erx

次に、を仮数と指数に分割します。r

ri=2eiri

ここで、は整数です。直感的に、e iは回答の精度を表します。riei

ニュートンの方法では、正確な有効桁数が約2倍になることがわかっています。だから私たちは選ぶことができます:

ei+1=2ei

少し操作すると、次のことがわかります。

w i = r i 2 x i = x

ei+1=2ei
wi=ri2
di=2ei+1wi xi
xi=x22eei+1
di=2ei+1wixi2ei+1
ri+1=2eiriridi2ei+1

すべての反復で:

xrix2e+ei

x=263231212231e=31r0=3e0=23412

次に:

e1=4,r1=11
e2=8,r2=180
e3=16,r3=46338
e4=32,r4=3037000481

eieei>2e

2633037000481×263231+32=3037000481

3037000499ei

bO(blogb)ri<2eiwieiei+1ei+12ei+1-ビット数。

O(eilogei)O(loge)O(2elog2e) operations. So the overall complexity is O(elog2e) operations, which is sub-quadratic in the number of bits in x. That ticks all the boxes.

However, this analysis hides an important principle which everyone working with large integers should keep in mind: because multiplication is superlinear in the number of bits, any multiplication operations should only be performed on integers which have the roughly the magnitude of the current precision (and, I might add, you should try to multiply numbers together which have a similar order of magnitude). Using integers larger than that is a waste of effort. Constant factors matter, and for large integers, they matter a lot.

As a final observation, two of the multiplications are of the form ab2c. Clearly it's wasteful to compute the all the bits of ab only to throw c of them away with a right-shift. Implementing a smart multiplication method which takes this into account is also left as an exercise.


This is great stuff. One comment, though: Isn't the bit-complexity of division asymptotically approximately the same as the bit-complexity of multiplication? So you're talking about something that gives a constant factor improvement, not an asymptotic improvement, right? That wasn't entirely clear from your answer.
D.W.

You say that multiplying two b-bit integers takes O(blgb) bit operations. I think the correct answer is something like O(blgb(lglgb)O(1)) (right?). You might want to indicate that you are ignoring poly-log-log factors (e.g., by putting a tilde over your big O, or something).
D.W.

1
@D.W. : No, he says that "multiplying two b-bit integers takes O(blogb) operations." The word "bit" only appears once in that; otherwise I would've already pointed that out.

It is a matter of constant factors, yes. The best large integer division algorithms use a technique very similar to the whole algorithm, such as Newton-Raphson iteration and doubling the effective precision on each iteration. A Newton-Raphson loop within a Newton-Raphson loop piles on the constant factors! Ricky Demer is correct; I was thinking in the word RAM model. I probably should have mentioned this.
Pseudonym
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.