带有回忆的尾部回复POW()算法?

发布于 2024-08-27 19:59:12 字数 668 浏览 13 评论 0原文

我正在寻找一种计算 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/2exp 的结果。

I'm looking for an algorithm to compute pow() that's tail-recursive and uses memoization to speed up repeated calculations.

Performance isn't an issue; this is mostly an intellectual exercise - I spent a train ride coming up with all the different pow() implementations I could, but was unable to come up with one that I was happy with that had these two properties.

My best shot was the following:

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)

It works, but it doesn't memoize the results of all calculations - only those with exponents 1..exp/2 and exp.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

凡尘雨 2024-09-03 19:59:12

如果您使用 SICP 第 1.2.4 节求幂。它不使用记忆,但一般方法是 O(log n) 而不是 O(n),因此您仍然应该看到改进。

我谈论练习1.16中迭代过程的解决方案 在这里

You'll get better performance if you use the successive squaring technique described in SICP section 1.2.4 Exponentiation. It doesn't use memoization, but the general approach is O(log n) instead of O(n), so you should still see an improvement.

I talk about the solution to the iterative process from exercise 1.16 here.

甜味超标? 2024-09-03 19:59:12

我认为您没有在缓存中记录正确的内容,当您使用不同的参数调用它时,映射会发生变化。

我认为你需要有一个 (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,它缓存的内容与它应该计算的内容完全不同。

I don't think you're recording the correct thing in your cache, the mapping changed when you call it with different arguments.

I think you need to have a cache of (base,exp) -> pow(base,exp).

I understand what ctr is for, and why only half of what you expect is recorded.

Consider calc_tailrec_mem(2,4): First level, pow(2,1) is recorded as 2, the next level = calc_tailrec_mem(2,3,...), and pow(2,2) is recorded. The next level is calc_tailrec_mem(2,2,...), but that is already saved in the cache, so the recursion stops.

The function is very confusing because it's caching something completely different from what it's supposed to be calculating, due to the acculumator and ctr.

谜兔 2024-09-03 19:59:12

这已经太晚了,但是任何人都在寻找答案,这里是:

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];
}

这使用 memo 数组 - 准确地说是一个 map - 来存储已经计算出的值。

This is way too late, but anyone out there looking for the answer, here it is:

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];
}

This uses the memo array - a map , to be exact - to store the already calculated values.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文