Одна из проблем метода Ньютона заключается в том, что он требует операции деления в каждой итерации, которая является самой медленной базовой целочисленной операцией.
Метод Ньютона для обратного квадратного корня, однако, не делает. Если - это число, для которого вы хотите найти , выполните итерацию:1x1x√
ri+1=12ri(3−xr2i)
Это часто выражается как:
d i = 1 - w i x r i + 1 = r i + r i d i
wi=r2i
di=1−wix
ri+1=ri+ridi2
Это три операции умножения. Деление на два может быть реализовано как сдвиг вправо.
Теперь проблема в том, что не является целым числом. Тем не менее, вы можете манипулировать им как таковым, реализуя с плавающей запятой вручную и выполняя кучу операций сдвига, чтобы компенсировать, когда это необходимо.r
Во-первых, давайте изменим масштаб :x
x′=2−2ex
где мы хотели бы, чтобы было больше, но близко к . Если мы запустим вышеупомянутый алгоритм на вместо , мы найдем . Тогда . 1 x ′ x r = 1x′1x′x√r=1x√′x−−√=2erx′
Теперь давайте разделим на мантиссу и показатель степени:r
ri=2−eir′i
где - целое число Интуитивно , что представляет точность ответа. e ir′iei
Мы знаем, что метод Ньютона примерно удваивает количество точных значащих цифр. Таким образом, мы можем выбрать:
ei+1=2ei
С небольшой манипуляцией мы находим:
ei+1=2ei
wi=r′i2
x′i=x22e−ei+1
di=2ei+1−w′ix′i2ei+1
r′i+1=2eir′i−r′idi2ei+1
На каждой итерации:
x−−√≈r′ix2e+ei
В качестве примера, давайте попробуем вычислить квадратный корень из . Мы знаем, что ответ . Обратный квадратный корень равен , поэтому мы установим (это масштаб проблемы) и для нашего начального предположения выберем и . (То есть мы выбираем для нашей начальной оценки .)x=2632312–√12√2−31e=31r′0=3e0=23412√
Затем:
e1=4,r′1=11
e2=8,r′2=180
e3=16,r′3=46338
e4=32,r′4=3037000481
Мы можем решить, когда прекратить итерации, сравнив с ; если я правильно рассчитал, должно быть достаточно хорошим. Мы остановимся здесь и найдем:eieei>2e
263−−−√≈3037000481×263231+32=3037000481
Правильный целочисленный квадратный корень - , поэтому мы довольно близки. Мы можем сделать еще одну итерацию или оптимизированную последнюю итерацию, которая не удваивает . Детали оставлены в качестве упражнения.3037000499ei
Чтобы проанализировать сложность этого метода, обратите внимание, что умножение двух разрядных целых чисел требует операций. Тем не менее, мы упорядочили вещи так, чтобы . Таким образом, умножение для вычисления умножает два числа бит, чтобы получить число -бит, а два других умножения умножают два числа -бит, чтобы получить -битный номер.bO(blogb)r′i<2eiwieiei+1ei+12ei+1
В каждом случае число операций на итерацию равно , и требуется итераций. Окончательное умножение порядка операций. Таким образом, общая сложность состоит из операций, которые субквадратичны по числу битов в . Это помечает все коробки.O(eilogei)O(loge)O(2elog2e)O(elog2e)x
Однако этот анализ скрывает важный принцип, который должен иметь в виду каждый, кто работает с большими целыми числами: поскольку умножение является суперлинейным по количеству битов, любые операции умножения должны выполняться только с целыми числами, которые имеют приблизительную величину текущей точности (и Я мог бы добавить, что вы должны попытаться умножить числа вместе, которые имеют схожий порядок). Использование целых чисел больше, чем это пустая трата усилий. Постоянные факторы имеют значение, а для больших целых они имеют большое значение.
В качестве последнего замечания, два умножения имеют вид . Очевидно, что расточительно вычислять все биты только для того, чтобы выбросить из них со сдвигом вправо. Реализация умного метода умножения, который учитывает это, также оставлена в качестве упражнения.ab2cabc