我一直在尝试在Julia中为Fibonacci函数做记忆。这就是我想出来的。
原始的未修改代码(用于控制目的)
function fib(x)
if x < 3
return 1
else
return fib(x-2) + fib(x-1)
end
end这是我第一次尝试
memory=Dict()
function memfib(x)
global memory
if haskey(memory,x)
return memory[x]
else
if x < 3
return memory[x] = 1
else
return memory[x] = memfib(x-2) + memfib(x-1)
end
end
end我的第二次尝试
memory=Dict()
function membetafib(x)
global memory
return haskey(memory,x) ? memory[x] : x < 3 ? memory[x]=1 : memory[x] = membetafib(x-2) + membetafib(x-1)
end我的第三次尝试
memory=Dict()
function memgammafib!(memory,x)
return haskey(memory,x) ? memory[x] : x < 3 ? memory[x]=1 : memory[x] = memgammafib!(memory,x-2) + memgammafib!(memory,x-1)
end有没有其他我不知道的方法呢?
发布于 2018-08-29 00:36:18
正如评论中指出的,Memoize.jl包肯定是最简单的选择。这要求您在定义时标记该方法。
然而,到目前为止最强大的方法是使用Cassette.jl,它允许您向预先存在的函数添加memoization,例如
fib(x) = x < 3 ? 1 : fib(x-2) + fib(x-1)
using Cassette
Cassette.@context MemoizeCtx
function Cassette.overdub(ctx::MemoizeCtx, ::typeof(fib), x)
get(ctx.metadata, x) do
result = recurse(ctx, fib, x)
ctx.metadata[x] = result
return result
end
end对正在发生的事情进行一点描述:
MemoizeCtx是我们正在运行的磁带“definingoverdub”,而不是原始的函数定义。我们使用它来检查元数据中是否存在参数dictionary.recurse(...)告诉磁带调用函数,但忽略顶级overload.
现在我们可以使用memoization来运行函数:
Cassette.overdub(MemoizeCtx(metadata=Dict{Int,Int}()), fib, 80)现在更酷的是,我们可以获取一个调用fib的现有函数,并在该函数中记住对fib的调用:
function foo()
println("calling fib")
@show fib(80)
println("done.")
end
Cassette.overdub(MemoizeCtx(metadata=Dict{Int,Int}()), foo)(Cassette对编译器来说仍然很难,所以第一次运行可能需要一段时间,但之后会很快)。
发布于 2018-08-30 02:29:43
发布于 2020-06-22 03:30:51
由于函数的参数是整数,您可以使用简单的数组,这将比Dict更快(请确保在缓存中为大参数使用BigInts,以避免溢出):
function fib(n, cache=sizehint!(BigInt[0,1],n))
n < length(cache) && return cache[n+1]
f = fib(n-1,cache) + fib(n-2,cache)
push!(cache,f)
return f
endhttps://stackoverflow.com/questions/52050262
复制相似问题