Хвост-рекурсивный алгоритм POW () с воспоминанием?
-
24-09-2019 - |
Вопрос
Я ищу алгоритм для вычисления pow()
Это рекурсивный хвост и использует мемузаризацию для ускорения повторных расчетов.
Производительность не проблема; Это в основном интеллектуальное упражнение - я провел поездку поезда со всеми разными pow()
Реализации, которые я мог, но не смог придумать то, что я был доволен тем, что имел эти два свойства.
Мой лучший удар был следующим:
def calc_tailrec_mem(base, exp, cache_line={}, acc=1, ctr=0):
if exp == 0:
return 1
elif exp == 1:
return acc * base
elif exp in cache_line:
val = acc * cache_line[exp]
cache_line[exp + ctr] = val
return val
else:
cache_line[ctr] = acc
return calc_tailrec_mem(base, exp-1, cache_line, acc * base, ctr + 1)
Работает, но это не воменяет результаты всех расчетов - только те, которые с показателями 1..exp/2
а также exp
.
Решение
Я не думаю, что вы записываете правильную вещь в вашем кэше, отображение изменено, когда вы называете его различными аргументами.
Я думаю, что вам нужно иметь кэш (Base, Exp) -> Pow (Base, Exp).
Я понимаю, что ctr
для, и почему только половина того, что вы ожидаете, записан.
Рассмотреть возможность calc_tailrec_mem(2,4)
: Первый уровень, POW (2,1) записывается как 2, следующий уровень = calc_tailrec_mem(2,3,...)
, и POW (2,2) записан. Следующий уровень calc_tailrec_mem(2,2,...)
, но это уже сохраняется в кэше, поэтому рекурсия останавливается.
Функция очень сбивает с толку, потому что она кэширует что-то совершенно отличное от того, что он должен быть рассчитанным, из-за аккумулятора и ctr
.
Другие советы
Вы получите лучшую производительность, если вы используете последовательную технику квадрата, описанную в SICP Раздел 1.2.4 Экспертизация. Отказ Он не использует мемузаризацию, но общий подход o (log n) вместо O (n), поэтому вы все равно должны увидеть улучшение.
Я говорю о решении итеративного процесса от упражнения 1.16 здесь.
Это слишком поздно, но кто-нибудь там ищет ответ, вот оно:
int powMem(int base,int exp){
//initializes once and for all
static map<int,int> memo;
//base case to stop the recursion
if(exp <= 1) return base;
//check if the value is already calculated before. If yes just return it.
if(memo.find(exp) != memo.end())
return memo[exp];
//else just find it and then store it in memo for further use.
int x = powMem(base,exp/2);
memo[exp] = x*x;
//return the answer
return memo[exp];
}
Это использует массив памятки - карта, чтобы быть точной - хранить уже рассчитанные значения.