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


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)=x2c.

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

뉴턴 방법의 각 반복 계산

xj+1=xj(xj2c)/(2xj)=0.5xj+c2xj.

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

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


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

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

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

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

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

7

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

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

ri+1=12ri(3xri2)

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

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

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

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

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

x=22ex

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

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

ri=2eiri

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

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

ei+1=2ei

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

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

반복 할 때마다 :

xrix2e+ei

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

그때:

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

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

2633037000481×263231+32=3037000481

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

To analyse the complexity of this method, note that multiplying two b-bit integers takes O(blogb) 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(eilogei), and there are O(loge) iterations required. The final multiplication is on the order of 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).
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.