Thuật toán căn bậc hai chính xác tùy ý?


9

Có bất kỳ thuật toán phụ nào được biết để tính sàn của căn bậc hai của một nsố nguyên bit không?

Thuật toán ngây thơ sẽ là một cái gì đó như

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

Điều này cần O(n)lặp đi lặp lại, mỗi lần liên quan đến bổ sung là O(n)thời gian, vì vậy đó là O(n^2)thời gian tổng thể. Có gì nhanh hơn không? Tôi biết rằng đối với trường hợp nhân, có các thuật toán đặc biệt làm tốt hơn thời gian bậc hai, nhưng tôi không thể tìm thấy bất cứ điều gì cho căn bậc hai.


Câu trả lời của tôi cho một cái gì đó liên quan có thể giúp cs.stackexchange.com/a/37338/12052 . Vấn đề duy nhất là, một phần của phương trình cần thiết bạn sẽ cần tìm theo kinh nghiệm để điều chỉnh độ chính xác của nó.
Francesco Gramano

@FrancescoGramano: Xin lỗi, tôi không nghĩ điều đó có ích.
Aryabhata

btw, đây là một phần yêu cầu bậc hai của một vấn đề lớn hơn? Bởi vì sự khác biệt giữa bậc hai đơn giản và bậc hai phức tạp có thể không lớn trong thực tế. Hay nó chỉ là lợi ích lý thuyết?
Aryabhata

@Aryabhata Xin lỗi tôi đã không thấy bình luận của bạn trước đó. Không, đó không phải là một phần của vấn đề lớn hơn, chỉ là sự tò mò.
Antimon

Câu trả lời:


5

Bạn có thể sử dụng phương pháp của Newton hoặc bất kỳ phương pháp nào khác để tìm các giá trị gần đúng với gốc của đa thức .p(x)=x2c

Tốc độ hội tụ cho phương pháp của Newton sẽ là bậc hai, có nghĩa là số bit được nhân đôi chính xác trong mỗi lần lặp. Điều này có nghĩa là lặp lại của phương pháp Newton.O(lgn)

Mỗi lần lặp của phương pháp Newton tính toán

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

Độ phức tạp bit của phép nhân là , để nhân hai số nguyên -bit (bỏ qua các yếu tố ). Độ phức tạp bit để phân chia (đến bit chính xác) là như nhau. Do đó, mỗi lần lặp có thể được tính trong các hoạt động . Nhân với số lần lặp , chúng tôi thấy rằng thời gian chạy tổng thể để tính căn bậc hai với bit chính xác là . Đây là tiểu phương.blglgbb O (nlgn)O(lgn)n O (n(lgn)2)O (blgb)blglgbbO (nlgn)O(lgn)nO (n(lgn)2)

Tôi nghĩ rằng một phân tích cẩn thận hơn cho thấy rằng điều này có thể được cải thiện thành thời gian chạy (bằng cách tính đến việc chúng ta chỉ cần biết mỗi trong khoảng bit chính xác, chứ không phải bit chính xác). Tuy nhiên, ngay cả các phân tích cơ bản hơn đã cho thấy một thời gian hoạt động rõ ràng là phụ.xjjnO (nlgn)xjjn


Trong nhị phân, người ta cũng có một dự đoán ban đầu tuyệt vời bằng cách sử dụng danh tính . Thay vì tính toán nhật ký, người ta có thể xấp xỉ là số chữ số trong . Ví dụ: . log 2 x x log 2 101.011 6x1/2=21/2log2xlog2xxlog21010116
Nick Alger

@DW: Nhưng không phải chúng ta đang tìm một căn bậc hai số nguyên sao? Nếu bạn thực hiện phép lặp phương thức của newton chỉ bằng số học số nguyên, thì chúng ta cần một số biện minh bổ sung cho yêu cầu , phải không? Mặt khác, chúng tôi đang giả định độ chính xác đủ lớn ... Xin lỗi nếu tôi thiếu một cái gì đó rõ ràng. O(logn)
Aryabhata

@DW:"Tốc độ hội tụ cho phương pháp của Newton" sẽ không phải là bậc hai nếu và tôi không biết điều gì xảy ra với các giá trị của không phải là không thực tế -negative. Ước tính của bạn về độ phức tạp của phép nhân là chặt chẽ hơn so với nhận xét sau đây cho thấy . Ngoài ra, chúng tôi "cần biết mỗi trong khoảng" "bit chính xác". cc=0c2xj2j

@Aryabhata:Chúng tôi không hoàn toàn "tìm kiếm một căn bậc hai số nguyên"; chúng tôi đang tìm kiếm "sàn của căn bậc hai". Bạn nói đúng về vấn đề số học số nguyên, mặc dù độ phức tạp bit tương tự giữ cho các phép toán dấu phẩy động.

1
@RickyDemer, vâng, là một trường hợp đặc biệt, bởi vì khi đó gốc rễ của có đa dạng 2, nhưng khi , gốc có đa 1 vì vậy phương pháp của Newton không có hội tụ bậc hai. Tôi giả sử không ai sẽ sử dụng phương pháp của Newton để tính căn bậc hai của (vì căn bậc hai của số 0 rõ ràng là số không). Vì vậy, những gì bạn đang cố gắng để nói? Nhận xét của bạn có phải là một nhận xét tầm thường được giải quyết bằng cách thêm một cái gì đó vào câu trả lời của tôi có nội dung "trường hợp đặc biệt là căn bậc hai của số không", hoặc có điều gì sâu hơn ở đây mà tôi đang thiếu không? p ( x ) c > 0 c = 0c=0p(x)c>0c=0
DW

6

Một trong những vấn đề với phương pháp của Newton là nó đòi hỏi một phép toán chia trong mỗi lần lặp, đây là phép toán số nguyên cơ bản chậm nhất.

Phương pháp của Newton cho căn bậc hai đối ứng , tuy nhiên, không. Nếu là số mà bạn muốn tìm , lặp lại:1x1x

ri+1=12ri(3xri2)

Điều này thường được thể hiện như sau:

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

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

Đó là ba hoạt động nhân. Việc phân chia theo hai có thể được thực hiện như một sự thay đổi.

Bây giờ vấn đề là không phải là số nguyên. Tuy nhiên, bạn có thể thao tác như vậy bằng cách thực hiện thủ công dấu phẩy động và thực hiện một loạt các thao tác thay đổi để bù khi thích hợp.r

Đầu tiên, hãy hủy bỏ :x

x=22ex

trong đó chúng tôi muốn lớn hơn, nhưng gần với, . Nếu chúng tôi chạy thuật toán trên trên thay vì , chúng tôi tìm thấy . Sau đó, .x1xxr=1xx=2erx

Bây giờ chúng ta hãy chia thành một mantissa và số mũ:r

ri=2eiri

trong đó là một số nguyên. Theo trực giác, đại diện cho độ chính xác của câu trả lời.riei

Chúng ta biết rằng phương pháp của Newton gần gấp đôi số chữ số có nghĩa chính xác. Vì vậy, chúng ta có thể chọn:

ei+1=2ei

Với một chút thao tác, chúng tôi tìm thấy:

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

Tại mỗi lần lặp:

xrix2e+ei

Ví dụ: hãy thử tính căn bậc hai của . Chúng tôi tình cờ biết rằng câu trả lời là . Căn bậc hai đối ứng là , vì vậy chúng tôi sẽ đặt (đây là thang đo của vấn đề) và theo dự đoán ban đầu của chúng tôi, chúng tôi sẽ chọn và . (Nghĩa là, chúng tôi chọn cho ước tính ban đầu của chúng tôi là .)x=263231212231e=31r0=3e0=23412

Sau đó:

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

Chúng ta có thể tìm ra khi nào nên dừng lặp lại bằng cách so sánh với ; nếu tôi đã tính toán chính xác, sẽ đủ tốt. Tuy nhiên, chúng tôi sẽ dừng ở đây và tìm:eieei>2e

2633037000481×263231+32=3037000481

Căn bậc hai số nguyên chính xác là , vì vậy chúng tôi khá gần nhau. Chúng ta có thể thực hiện một lần lặp khác hoặc thực hiện một lần lặp cuối cùng được tối ưu hóa mà không nhân đôi . Các chi tiết được để lại như một bài tập.3037000499ei

Để phân tích độ phức tạp của phương pháp này, lưu ý rằng nhân hai số nguyên -bit cần các thao tác . Tuy nhiên, chúng tôi đã sắp xếp mọi thứ sao cho . Vì vậy, phép nhân để tính nhân hai số -bit để tạo ra một số và hai phép nhân khác nhân hai số để tạo ra một số số -bit.bO(blogb)ri<2eiwieiei+1ei+12ei+1

Trong mỗi trường hợp, số lượng thao tác trên mỗi lần lặp là và có các lần lặp . Phép nhân cuối cùng là theo thứ tự các phép toán . Vì vậy, độ phức tạp tổng thể là các phép toán , là bậc hai trong số các bit trong . Đó là tất cả các hộp.O ( log e ) O ( 2 e log 2 e ) O ( e log 2 e ) xO(eilogei)O(loge)O(2elog2e)O(elog2e)x

Tuy nhiên, phân tích này ẩn chứa một nguyên tắc quan trọng mà mọi người làm việc với các số nguyên lớn nên ghi nhớ: bởi vì phép nhân là siêu tuyến trong số bit, bất kỳ thao tác nhân nào chỉ nên được thực hiện trên các số nguyên có độ lớn gần bằng độ chính xác hiện tại (và , Tôi có thể thêm, bạn nên cố gắng nhân các số với nhau có thứ tự cường độ tương tự nhau). Sử dụng số nguyên lớn hơn đó là một sự lãng phí nỗ lực. Các yếu tố không đổi quan trọng, và đối với các số nguyên lớn, chúng quan trọng rất nhiều.

Như một quan sát cuối cùng, hai trong số các phép nhân có dạng . Rõ ràng thật lãng phí khi tính tất cả các bit của chỉ để ném chúng đi với một ca phải. Việc thực hiện một phương pháp nhân thông minh có tính đến điều này cũng được coi là một bài tập. abcab2cabc


Đây là công cụ tuyệt vời. Mặc dù vậy, một nhận xét: Không phải độ phức tạp của phép chia không tương tự như độ phức tạp của phép nhân? Vì vậy, bạn đang nói về một cái gì đó cải thiện yếu tố liên tục, không phải là cải thiện tiệm cận, phải không? Điều đó không hoàn toàn rõ ràng từ câu trả lời của bạn.
DW

Bạn nói rằng nhân hai số nguyên -bit sẽ có các phép toán bit . Tôi nghĩ rằng câu trả lời đúng là một cái gì đó giống như (phải không?). Bạn có thể muốn chỉ ra rằng bạn đang bỏ qua các yếu tố log-log (ví dụ: bằng cách đặt dấu ngã lên chữ O lớn của bạn hoặc một cái gì đó). O ( b lg b ) O ( b lg b ( lg l g b ) O ( 1 ) )bO(blgb)O(blgb(lglgb)O(1))
DW

1
@DW:Không, ông nói rằng "nhân hai số nguyên -bit có các thao tác ." Từ "bit" chỉ xuất hiện một lần trong đó; nếu không thì tôi đã chỉ ra điều đó. O ( b log b )bO(blogb)

Đó là một vấn đề của các yếu tố không đổi, vâng. Các thuật toán chia số nguyên lớn tốt nhất sử dụng một kỹ thuật rất giống với toàn bộ thuật toán, chẳng hạn như phép lặp Newton-Raphson và nhân đôi độ chính xác hiệu quả trên mỗi lần lặp. Một vòng lặp Newton-Raphson trong vòng lặp Newton-Raphson chồng chất lên các yếu tố không đổi! Ricky Demer là chính xác; Tôi đã suy nghĩ trong mô hình RAM từ. Tôi có lẽ nên đề cập đến điều này.
Bút danh
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.