임의 정밀도 정수 제곱근 알고리즘?


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

btw,이 차 이차 요구 사항이 더 큰 문제의 일부입니까? 단순한 이차와 복잡한 이차의 차이점이 실제로 그렇게 크지 않을 수도 있기 때문입니다. 아니면 단지 이론적 인 관심입니까?
— Aryabhata

@Aryabhata 죄송합니다. 이전에 댓글을 보지 못했습니다. 아니요, 더 큰 문제의 일부가 아니라 호기심입니다.
— 안티몬

답변:


5

다항식의 근에 근사값을 구하기 위해 Newton의 방법 또는 다른 여러 방법을 사용할 수 있습니다p(x)=x2−c.

Newton의 방법에 대한 수렴 속도는 2 차적입니다. 즉, 올바른 반복 횟수는 각 반복에서 두 배가됩니다. 이것은 의미O(lg⁡n) 뉴턴의 방법으로 충분하다.

뉴턴 방법의 각 반복 계산

xj+1=xj−(xj2−c)/(2xj)=0.5xj+c2xj.

곱셈의 비트 복잡성은 O (blg⁡b)두 곱하기 b비트 정수 (무시) lg⁡lg⁡b요인). 나누기의 비트 복잡도b정밀도의 비트)는 동일합니다. 따라서 각 반복은O (nlg⁡n)작업. 에 의해 곱하기O(lg⁡n) 반복, 우리는 제곱근을 계산하는 전체 실행 시간을 n 정밀한 비트는 O (n(lg⁡n)2). 이것은 이차 이하입니다.

더 신중한 분석에 따르면 이것이 향상 될 수 있다고 생각합니다. 영형 (엔lg⁡엔) 러닝 타임 (각각 알아야 할 것을 고려하여 xj ~ 안에 j 정밀도가 아닌 비트 n정밀한 비트). 그러나 더 기본적인 분석조차도 이미 이차적 인 실행 시간을 보여줍니다.


이진수로도 정체성을 사용하여 큰 초기 추측이 있습니다. x1/2=21/2log2⁡엑스. 로그를 계산하는 대신 대략적으로로그2⁡엑스 의 자리수로 엑스. 예 :로그2⁡101011≈6.
— Nick Alger

@DW : 그러나 우리는 정수 제곱근을 찾고 있지 않습니까? 정수 산술 만 사용하여 뉴턴의 메소드 반복을 수행하는 경우 우리는O(log⁡n)주장하지 않습니까? 그렇지 않으면, 우리는 이미 충분히 큰 정밀도를 가정하고 있습니다 ... 분명한 것이 빠지면 미안합니다.
— Aryabhata

@DW : "뉴턴 방법의 수렴 속도"는 씨=0, 그리고 나는 가치에 어떤 일이 일어나는지 모른다 씨 그것은 음이 아닌 사실이 아닙니다. 곱셈의 비트 복잡도에 대한 추정치는 다음 말이 제시하는 것보다 더 엄격합니다 . 또한, 우리는 각각을 알아야합니다 엑스제이 ~ 안에 2제이 "정도의 비트".

@Aryabhata : 우리는 "정수 제곱근을 찾고 있지 않습니다"; 우리는 "제곱근 바닥"을 찾고 있습니다. 부동 소수점 연산에 대해 동일한 비트 복잡성이 유지되지만 정수 산술 문제에 대해서는 맞습니다.

1
@RickyDemer, 예, 씨=0 특별한 경우입니다. 피(엑스) 다중도 2를 갖지만 씨>0루트는 다중도를 가지므로 Newton의 방법 은 차 융합이있다. 아무도 뉴턴의 방법을 사용하여 제곱근을 계산하지 않을 것이라고 가정합니다.씨=0(0의 제곱근은 분명히 0이기 때문에). 무슨 말을하려고합니까? 귀하의 의견은 "응답에 0의 제곱근"이라는 내용을 추가하여 해결되는 사소한 의견입니까, 아니면 내가 누락 된 부분이 있습니까?
— DW

7

Newton의 방법의 문제점 중 하나는 각 반복마다 나누기 연산이 필요하다는 것입니다. 이는 가장 느린 기본 정수 연산입니다.

그러나 역 제곱근에 대한 뉴턴의 방법은 그렇지 않습니다. 만약엑스 찾고자하는 번호입니다 1엑스반복 :

ri+1=12ri(3−xri2)

이것은 종종 다음과 같이 표현됩니다 :

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

세 번의 곱셈 연산입니다. 2 개로 나누는 것은 오른쪽 이동으로 구현할 수 있습니다.

이제 문제는 r정수가 아닙니다. 그러나 부동 소수점을 수동으로 구현하고 적절한 경우 보상하기 위해 많은 시프트 연산을 수행하여이를 조작 할 수 있습니다.

먼저 크기를 조정하겠습니다 x:

x′=2−2ex

우리가 원하는 곳 x′ 보다 크지 만 가까이 있어야합니다 1. 위의 알고리즘을 실행하면x′ 대신에 x, 우리는 찾는다 r=1x′. 그때,x=2erx′.

이제 나누자 r 가수와 지수로 :

ri=2−eiri′

어디 ri′정수입니다. 직관적으로ei 답의 정확성을 나타냅니다.

우리는 뉴턴의 방법이 정확한 유효 자릿수의 두 배를 가짐을 알고 있습니다. 그래서 우리는 선택할 수 있습니다 :

ei+1=2ei

약간의 조작만으로 우리는 다음을 발견합니다.

ei+1=2ei
wi=ri′2
xi′=x22e−ei+1
di=2ei+1−wi′xi′2ei+1
ri+1′=2eiri′−ri′di2ei+1

반복 할 때마다 :

x≈ri′x2e+ei

예를 들어, 제곱근을 계산해 봅시다 x=263. 우리는 그 답이2312. 상호 제곱근은122−31그래서 우리는 설정합니다 e=31 (이것은 문제의 규모입니다) 첫 번째 추측을 위해 우리는 선택할 것입니다 r0′=3 과 e0=2. (즉, 우리는34 초기 추정치 12.)

그때:

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

우리는 반복을 멈추는 시점을 비교하여 해결할 수 있습니다. ei 에 e; 내가 정확하게 계산했다면ei>2e충분해야합니다. 우리는 여기서 멈추고 다음을 찾습니다.

263≈3037000481×263231+32=3037000481

올바른 정수 제곱근은 3037000499우리는 아주 가깝습니다. 또 다른 반복을 수행하거나 최적화되지 않은 최종 반복을 수행 할 수 있습니다.ei. 세부 사항은 연습으로 남습니다.

To analyse the complexity of this method, note that multiplying two b-bit integers takes O(blog⁡b) operations. However, we have arranged things so that ri′<2ei. So the multiplication to calculate wi multiplies two ei-bit numbers to produce a ei+1-bit number, and the other two multiplications multiply two ei+1-bit numbers to produce a 2ei+1-bit number.

In each case, the number of operations per iteration is O(eilog⁡ei), and there are O(log⁡e) iterations required. The final multiplication is on the order of O(2elog⁡2e) operations. So the overall complexity is O(elog2⁡e) 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(blg⁡b) bit operations. I think the correct answer is something like O(blg⁡b(lg⁡lgb)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).
— DW

1
@DW : 아니, 그는 "2를 곱하면 비비트 정수는 영형(비로그⁡비) 작업. " "비트"라는 단어는 한 번만 나타납니다. 그렇지 않으면 나는 이미 그것을 지적했을 것입니다.

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.
— 가명
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.