Существует несколько алгоритмов "spigot", которые последовательно вычисляют цифры неограниченным образом.Это полезно, потому что вы можете просто вычислить «следующую» цифру через постоянное число основных арифметических операций, не определяя заранее, сколько цифр вы хотите произвести.
Они применяют серию последовательных преобразований, так что следующеецифры приходят на 1-е место, так что на них не влияют ошибки округления чисел с плавающей точкой.Эффективность высока, потому что эти преобразования могут быть сформулированы как умножения матриц, которые сводятся к целочисленным сложениям и умножению.дробные части факториалов (обратите внимание, что для того, чтобы сделать ряд регулярным, мы переместили 1
влево):
(e - 1) = 1 + (1/2)*(1 + (1/3)*(1 + (1/4)...))
Мы можем определить ряд функций f1 (x) ... fn(x) таким образом:
f1(x) = 1 + (1/2)x
f2(x) = 1 + (1/3)x
f3(x) = 1 + (1/4)x
...
Значение e находится из состава всех этих функций:
(e-1) = f1(f2(f3(...fn(x))))
Мы можем наблюдать, что значение x в каждой функцииопределяется следующей функцией, и что каждое из этих значений ограничено диапазоном [1,2], то есть для любой из этих функций значение x будет 1 <= x <= 2
, так как этоВ этом случае мы можем установить нижнюю и верхнюю границы для e, используя значения 1 и 2 для x соответственно:
lower(e-1) = f1(1) = 1 + (1/2)*1 = 3/2 = 1.5
upper(e-1) = f1(2) = 1 + (1/2)*2 = 2
Мы можем повысить точность, составив функции, определенные выше, и когда цифра maв нижней и верхней границах мы знаем, что наше вычисленное значение e точно соответствует этой цифре:
lower(e-1) = f1(f2(f3(1))) = 1 + (1/2)*(1 + (1/3)*(1 + (1/4)*1)) = 41/24 = 1.708333
upper(e-1) = f1(f2(f3(2))) = 1 + (1/2)*(1 + (1/3)*(1 + (1/4)*2)) = 7/4 = 1.75
Поскольку цифры 1 и 10 совпадают, можно сказать, что приближение (e-1) с точностью до десятых составляет 1,7.Когда первая цифра совпадает между верхней и нижней границами, мы вычитаем ее, а затем умножаем на 10 - таким образом, рассматриваемая цифра всегда находится на месте 1, где точность с плавающей запятой высока.
РеальноеОптимизация происходит из техники линейной алгебры, описывающей линейную функцию как матрицу преобразования.Составление функций соответствует матричному умножению, поэтому все эти вложенные функции могут быть сведены к простому целочисленному умножению и сложению.Процедура вычитания цифры и умножения на 10 также представляет собой линейное преобразование, и, следовательно, также может быть выполнено умножением матрицы.
Другое объяснение метода: http://www.hulver.com/scoop/story/2004/7/22/153549/352
Бумага, котораяописывает алгоритм: http://www.cs.ox.ac.uk/people/jeremy.gibbons/publications/spigot.pdf
Краткое введение в выполнение линейных преобразований с помощью матричной арифметики: https://people.math.gatech.edu/~cain/notes/cal6.pdf
Примечание: этот алгоритм использует преобразования Мёбиуса, которые представляют собой тип линейного преобразования, кратко описанногов бумаге Гиббонов.