Spigot-алгоритм

Материал из Википедии — свободной энциклопедии
Перейти к навигации Перейти к поиску

Spigot-алгоритм (упоминается также как «алгоритм крана», или, что более точно, «алгоритм затвора», так как его работа похожа на движение затвора автомата, выбрасывающего очередной патрон) — алгоритм вычисления значения математических констант, например или e, который позволяет определить цифры в некоторой заранее выбранной системе счисления (обычно двоичной или с основанием в виде степени двойки) слева направо. Название происходит от английского слова «spigot», означающего кран или вентиль для управления потоком жидкости.

Интерес к Spigot-алгоритму усилился в период раннего развития вычислительной математики из-за жестких ограничений на объёмы памяти. Первый подобный алгоритм вычисления знаков числа e встречается в работе Артура Сейла (Arthur Harry John Sale) 1986 года[1]. Название «Spigot-алгоритм», скорее всего, придумали Стенли Рабинович и Стен Вагон[2].

Алгоритм, предложенный Рабиновичем и Вагоном, — ограниченный в том смысле, что количество вычисляемых знаков должно быть определено заранее. Джереми Гиббонс (Jeremy Gibbons) в 2004 г. вводит обобщение под названием «потоковый алгоритм»[3], в котором вычисления можно проводить бесконечно долго, тем самым убрав ограниченность исходного алгоритма. Ещё одним улучшением Spigot-алгоритма стал алгоритм, позволяющий вычислить конкретный знак без необходимости определения предыдущих знаков числа. Например, Формула Бэйли — Боруэйна — Плаффа для вычисления произвольных знаков в 16-ричной записи числа .

Продемонстрируем работу Spigot-алгоритма на примере вычисления двоичных знаков натурального логарифма 2 на основе формулы:

Чтобы найти двоичные знаки начиная с 8-го, умножим число на 27 (так как 7=8-1):

Затем разделим бесконечный ряд на «голову», в которой степень двойки больше или равна нулю, и «хвост» с отрицательными степенями:

Нас интересует только дробная часть этого значения, поэтому мы заменяем каждое слагаемое в первой сумме («голове») на:

Вычислим каждое слагаемое отдельно, отбрасывая целую часть:

k A = 27−k B = A (mod k) C = B / k C (mod 1)
1 64 0 0 0
2 32 0 0 0
3 16 1 1/3 1/3
4 8 0 0 1/3
5 4 4 4/5 2/15
6 2 2 1/3 7/15
7 1 1 1/7 64/105

Вычислим несколько первых элементов из «хвоста». Выбираем такую часть этой суммы, чтобы ошибка вычисления была меньше искомого 7-го знака числа.

k D = 1/k2k−7 D Макс. ошибка
8 1/16 1/16 1/16
9 1/36 13/144 1/36
10 1/80 37/360 1/80

Суммируя «голову» и несколько первых элементов «хвоста», мы получим:

таким образом цифрами с 8-й по 11-ю в двоичной записи числа являются 1, 0, 1, 1. Заметьте, что мы не вычисляли значений предыдущих семи цифр. Информация об этих цифрах была умышленно отброшена при использовании модульной арифметики при вычислении «головы».

Данный подход можно использовать для вычисления произвольного n-го знака в двоичной записи числа ln(2). Количество слагаемых в «голове» линейно растёт с увеличением n, но сложность вычисления элементов растёт логарифмически при использовании методов возведения в степень по модулю. Точность вычисления, промежуточные вычисления и количество нужных слагаемых из «хвоста» не зависят от n, а зависят только от количества двоичных знаков, которые нужно вычислить. Используя дробные числа одинарной точности, можно найти около 12 двоичных знаков независимо от начальной позиции.

Примечания

[править | править код]
  1. Sale, AHJ. The calculation of e to many significant digits (англ.) // The Computer Journal[англ.] : journal. — 1968. — Vol. 11, no. 2. — P. 229—230. — doi:10.1093/comjnl/11.2.229. Архивировано 19 сентября 2016 года.
  2. Rabinowitz, Stanley; Wagon, Stan. A Spigot Algorithm for the Digits of Pi (англ.) // American Mathematical Monthly : journal. — 1995. — Vol. 102, no. 3. — P. 195—203. — doi:10.2307/2975006. Архивировано 13 июля 2019 года.
  3. Gibbons, Jeremy Unbounded Spigot Algorithms for the Digits of Pi (24 мая 2004). Дата обращения: 9 декабря 2019. Архивировано 29 августа 2008 года.