Быстрое возведение в степень, когда требуются только первые k цифр? - PullRequest
7 голосов
/ 11 марта 2009

Это на самом деле для соревнования по программированию, но я очень старался и даже не представлял себе, как это сделать.

Найдите первую и последнюю k цифр n m , где n и m могут быть очень большими ~ 10 ^ 9.

Для последних k цифр я реализовал модульное возведение в степень.

Для первого k я подумал об использовании биномиальной теоремы до определенных степеней, но это требует довольно много вычислений для факториалов, и я не уверен, как найти оптимальную точку, в которой n ^ m можно разложить как (x + у) м .

Так есть ли какой-нибудь известный способ найти первые k цифр, не выполняя весь расчет?

Обновление 1 <= k <= 9, и k всегда будет <= цифрами в n <sup>m

Ответы [ 4 ]

4 голосов
/ 11 марта 2009

не уверен, но на ум приходит тождество n m = exp10 (m log10 (n)) = exp (q (m log (n) / q)), где q = log (10) наряду с тем фактом, что первые K цифр exp10 (x) = первые K цифр exp10 (frac (x)), где frac (x) = дробная часть x = x - floor (x).

Чтобы быть более точным: первые K цифр n m являются первыми K цифрами его мантисса = exp (frac (m log (n) / q) * q ), где q = log (10).

Или вы можете даже пойти дальше в этом упражнении по учету и использовать exp ((frac (m log (n) / q) -0.5) * q) * sqrt (10), который также имеет ту же мантиссу (+, следовательно, те же самые первые K цифр), так что аргумент функции exp () центрируется вокруг 0 ​​(и между +/- 0.5 log 10 = 1.151) для быстрой сходимости.

(Некоторые примеры: предположим, что вы хотели первые 5 цифр 2 100 . Это равняется первым 5 цифрам exp ((frac (100 log (2) / q) -0,5) * q) * sqrt (10) = 1,267650600228226. Фактическое значение 2 100 составляет 1,267650600228229e + 030 в соответствии с MATLAB, у меня нет удобной библиотеки bignum. Для мантиссы 2 1,000,000,000 Я получаю 4.612976044195602, но у меня нет способа проверить .... Есть страница на простых числах Мерсенна , где кто-то уже проделал тяжелую работу; 2 20996011 -1 = 125 976 895 450 ... и моя формула дает 1,259768950493908, рассчитанное в MATLAB, которое не работает после 9-й цифры.)

Я мог бы использовать ряд Тейлора (для exp и log , а не для n m ) вместе с их границами ошибок и продолжать добавлять термины до появления ошибки границы опускаются ниже первых K цифр. (обычно я не использую ряды Тейлора для приближения функций - их ошибка оптимизирована таким образом, чтобы быть максимально точной вокруг одной точки, а не в течение заданного интервала - но у них есть преимущество в том, что они математически просты, и вы может повысить точность до произвольной, просто добавив дополнительные термины)

Для логарифмов я бы использовал любое ваше любимое приближение.

2 голосов
/ 06 октября 2010

Хорошо. Мы хотим вычислить alt text и получить только n первые цифры.

Рассчитать alt text с помощью следующих итераций:

alt text

У вас есть alt text. Рассчитать каждый alt text не совсем так. Дело в том, что относительная ошибка alt text меньше чем n раз относительная ошибка a .

Вы хотите получить окончательную относительную ошибку меньше alt text. Таким образом, относительная ошибка на каждом шаге может составлять alt text. Удалите последние цифры на каждом шаге.

Например, a = 2, b = 16, n = 1. Конечная относительная ошибка 10 ^ {- n} = 0,1. Относительная погрешность на каждом шаге составляет 0,1 / 16> 0,001. Таким образом, 3 цифры важны на каждом шаге. Если n = 2, вы должны сохранить 4 цифры.

2 (1), 4 (2), 8 (3), 16 (4), 32 (5), 64 (6), 128 (7), 256 (8), 512 (9), 1024 ( 10) -> 102, 204 (11), 408 (12), 816 (13), 1632 (14) -> 163, 326 (15), 652 (16).

Ответ: 6.

Этот алгоритм имеет O (b) . Но это легко изменить, чтобы получить O (log b)

0 голосов
/ 11 марта 2009

Вы смотрели на возведение в степень в квадрате ? Возможно, вам удастся изменить один из методов так, чтобы вы вычисляли только то, что необходимо.

В моем последнем классе алгоритмов мы должны были реализовать нечто похожее на то, что вы делаете, и я смутно помню, что эта страница была полезной.

0 голосов
/ 11 марта 2009

Предположим, вы усекаете на каждом шаге? Не уверен, насколько точным это будет, но, например, принять п = 11 м = некоторое большое число и вы хотите первые 2 цифры.

рекурсивно:

  1. 11 x 11 -> 121, усечение -> 12 (1 усечение или округление) затем возьмите усеченное значение и снова поднимите
  2. 12 x 11 -> 132 усеченных -> 13 повторить,

  3. (132 усечено) x 11 -> 143. ...

и, наконец, добавьте эквивалент # 0 к числу выполненных вами усечений.

...