Довільна точність цілочислового алгоритму квадратного кореня?


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)загальний час. Чи є щось швидше? Я знаю, що для випадку множення існують спеціальні алгоритми, які працюють краще, ніж квадратичний час, але я не можу знайти нічого для квадратних коренів.


Моя відповідь на щось пов'язане може допомогти cs.stackexchange.com/a/37338/12052 . Єдина проблема полягає в тому, що частина необхідного рівняння вам потрібно було б емпірично знайти для налаштування його точності.
Франческо Грамано

@FrancescoGramano: Вибачте, я не думаю, що це допомагає.
Ар'ябхата

btw, чи є ця підквадратична вимога більшою проблемою? Тому що різниця між простою квадратичною та складною підквадратичною на практиці може бути не такою великою. Або це просто теоретичний інтерес?
Арябхата

@Aryabhata Вибачте, що раніше не бачив ваш коментар. Ні, це не частина більшої проблеми, просто цікавість.
Сурма

Відповіді:


5

Для пошуку наближень до коренів многочлена можна скористатися методом Ньютона або будь-яким з ряду інших методівp(x)=x2c.

Швидкість конвергенції за методом Ньютона буде квадратичною, що означає, що кількість бітів, правильних, подвоюється в кожній ітерації. Це означаєO(lgn) ітерацій методу Ньютона достатньо.

Кожна ітерація методу Ньютона обчислюється

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

Бітова складність множення є O (blgb), помножити два b-бітові цілі числа (ігнорування lglgbчинники). Бітова складність для поділу (доbбіт точності) однаковий. Тому кожну ітерацію можна обчислитиO (nlgn)операції. Множення наO(lgn) Ітерації, ми знаходимо, що загальний час роботи для обчислення квадратного кореня n біт точності є O (n(lgn)2). Це підквадратично.

Я думаю, що більш ретельний аналіз показує, що це можна вдосконалити O (nlgn) час роботи (враховуючи, що нам потрібно знати лише кожного xj до в межах близько j біт точності, а не nбіт точності). Однак навіть більш базовий аналіз вже показує час роботи, який явно підквадратичний.


У двійковій також є чудова початкова здогадка з використанням ідентичності x1/2=21/2log2x. Замість обчислення журналу можна наблизитисьlog2x як кількість цифр у x. Наприклад,log21010116.
Нік Алгер

@DW: Але хіба ми не шукаємо цілого квадратного кореня? Якщо ви робите ітерацію методу Ньютона, використовуючи лише цілу арифметику, тоді нам потрібно додаткове обґрунтування дляO(logn)стверджуємо, чи не так? Інакше ми припускаємо досить велику точність ... Вибачте, якщо я пропускаю щось очевидне.
Ар'ябхата

@DW: "Швидкість конвергенції методу Ньютона" не буде квадратичною, якщо c=0, і я не знаю, що відбувається з значеннями c які не є негативними. Ваша оцінка бітової складності множення є чіткішою, ніж підказує наступне зауваження . Також нам "потрібно знати кожного xj в межах приблизно " 2j "шматочки точності".

@Aryabhata: Ми не зовсім «шукаємо цілий квадратний корінь»; ми шукаємо "підлогу квадратного кореня". Ви маєте рацію щодо цілочисельної арифметичної проблеми, хоча для операцій з плаваючою комою є однакові складності бітів.

1
@RickyDemer, так, c=0 є особливим випадком, тому що тоді корінь p(x) має кратність 2, але коли c>0, Корінь має кратність 1 , так метод Ньютона має має квадратичну збіжність. Я припускаю, що ніхто не використовує метод Ньютона для обчислення квадратного кореняc=0(адже квадратний корінь нуля очевидно дорівнює нулю). То що ти намагаєшся сказати? Чи є ваш коментар тривіальним коментарем, на який звертається, додавши щось до моєї відповіді, що говорить "особливий випадок квадратного кореня нуля", чи є щось глибше, чого я пропускаю?
DW

7

Одна з проблем методу Ньютона полягає в тому, що він вимагає операції ділення в кожній ітерації, яка є найповільнішою базовою цілочисельною операцією.

Однак метод Ньютона для зворотного квадратного кореня не відповідає. Якщоx - це номер, який ви хочете знайти 1x, повторіть:

ri+1=12ri(3xri2)

Це часто виражається як:

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

Це три операції множення. Поділ на два може бути реалізований як зсув-направо.

Зараз проблема полягає в тому rне є цілим числом. Однак ви можете маніпулювати нею, застосовуючи плаваючу крапку вручну і виконуючи купу операцій зсуву, щоб компенсувати, коли це доречно.

Спочатку давайте розширювати масштаб x:

x=22ex

куди б ми хотіли x бути більшим за, але близьким до, 1. Якщо ми запустимо вищевказаний алгоритмx замість x, ми знайшли r=1x. Тоді,х=2еrх'.

Тепер давайте розділимо r в мантісу і показник:

ri=2-еiri'

де ri'- ціле число. Інтуїтивно,еi представляють точність відповіді.

Ми знаємо, що метод Ньютона приблизно подвоює кількість точних значущих цифр. Тож ми можемо вибрати:

еi+1=2еi

Трохи маніпулюючи, ми знаходимо:

еi+1=2еi
шi=ri'2
хi'=х22е-еi+1
гi=2еi+1-шi'хi'2еi+1
ri+1=2eiriridi2ei+1

На кожній ітерації:

xrix2e+ei

Як приклад, спробуємо обчислити квадратний корінь x=263. Ми випадково знаємо, що відповідь є2312. Зворотний квадратний корінь є12231, тому ми встановимо 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має бути досить хорошим. Ми зупинимося тут, і знайдемо:

2633037000481×263231+32=3037000481

Правильним цілим квадратним коренем є 3037000499, тож ми досить близько. Ми можемо зробити ще одну ітерацію або оптимізовану остаточну ітерацію, яка не подвоюєтьсяei. Деталі залишаються як вправа.

Щоб проаналізувати складність цього методу, зауважимо, що множимо два b-бітні цілі числа займає O(blogb)операції. Однак ми влаштували речі такri<2ei. Отже множення для обчисленняwi множить два ei-бітові числа для отримання a ei+1-бітове число, а інші два множення множать два ei+1-бітові числа для отримання a 2ei+1-бітове число.

У кожному випадку кількість операцій за ітерацію становить O(eilogei), і є O(loge)необхідні ітерації. Остаточне множення йде на порядокO(2elog2e)операції. Тож загальна складність єO(elog2e) операцій, яка є субквадратичною за кількістю бітів у x. Це тикає всі коробки.

Однак цей аналіз приховує важливий принцип, про який повинні пам’ятати усі, хто працює з великими цілими числами: оскільки множення є надлінійним за кількістю бітів, будь-які операції множення повинні виконуватися лише на цілих числах, що мають приблизно величину поточної точності (і , Можу додати, вам слід спробувати помножити числа, які мають аналогічний порядок). Використання цілих чисел, більших за це, є марною витратою зусиль. Постійні фактори мають значення, а для великих цілих чисел вони мають велике значення.

Як підсумкове спостереження, два з множень мають форму ab2c. Очевидно, що марно обчислювати всі бітиab тільки кинути cз них геть правою зміною. Реалізація розумного методу множення, який враховує це, також залишається вправою.


Це чудові речі. Хоча один коментар: Чи не бітова складність ділення асимптотично приблизно така ж, як і бітова складність множення? Отже, ви говорите про те, що дає постійне поліпшення факторів, а не асимптотичне поліпшення, правда? Це було не зовсім зрозуміло з вашої відповіді.
DW

Ви кажете, що множачи два б-бітні цілі числа займає О(бlgб)бітові операції. Я думаю, що правильна відповідь - це щось на кшталтО(бlgб(lgлгб)О(1))(правда?). Можливо, ви хочете вказати, що ви ігноруєте фактори журналу poly-log (наприклад, наклавши нахил над великим O чи іншим).
DW

1
@DW: Ні, він каже, що «множення двох б-бітні цілі числа займає О(бжурналб) операції. " Слово "біт" з’являється лише один раз у цьому; інакше я б це вже вказав.

Це питання постійних факторів, так. Найкращі алгоритми великого цілого поділу використовують метод, дуже подібний до всього алгоритму, такий як ітерація Ньютона-Рафсона та подвоєння ефективної точності на кожній ітерації. Цикл Ньютона-Рафсона в циклі Ньютона-Рафсона накопичується на постійні фактори! Рікі Демер правильний; Я думав у слові модель RAM. Я, мабуть, мав би про це згадати.
Псевдонім
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.