问题描述
do
local function index(n,m)
return n*(n+1)//2 + m
end
local binomtable = {}
function binom3(n,m)
if n<0 or m<0 or m>n then return 0 end
if n=0 or m=0 or m=n then return 1 end
local i = index(n,m)
local v = binomtable[i]
if v then return v end
v = binom3(n-1,m-1) + binom3(n-1,m)
binomtable[i] = v
return v
end
end
我想知道什么
if v then return v end
表示。
谢谢!
解决方法
简短的回答是,如果if v then return v end
是真实的,即既不是v
也不是false
,则返回值nil
。否则,函数将继续计算v
的值,将该值存储在binomtable
中,最后返回它。更有趣的问题是,为什么函数要执行所有这些操作?
在发布的代码中,binom3
是一个递归函数。使用递归调用v = binom3(n-1,m-1) + binom3(n-1,m)
时,将会有很多重复的工作,这意味着浪费大量的空间和时间。考虑:
binom3(4,2)
--> binom3(3,1) + binom3(3,2)
--> binom3(2,0) + binom3(2,1) + binom3(2,2)
--> 1 + binom3(1,0) + binom3(1,1) + binom3(1,1) + 1
请注意,在第二个简化中,有两个相同的术语:
binom3(2,1)
没有理由两次计算项binom3(2,1)
,这样做意味着这对项:
binom3(1,1)
如第三次减法所示,也必须计算两次。仅计算一次binom3(2,1)
,然后保存结果供以后在较大的计算中使用,将是明智的。当m
和n
较大且计算数量呈指数爆炸式增长时,这对性能而言是非常重要的问题,无论是所需的内存量还是所需的时间。
发布的代码正在使用memoization来提高性能。进行计算时,它将存储在表binomtable
中。在进行任何计算之前,请先咨询binomtable
。首先,将v
设置为binomtable[i]
的值;如果该值是任何真实值(Lua中的任何整数都是真实值),则仅返回该值而无需递归计算。否则,如果返回nil
(即,尚未存储任何计算值),则该函数将继续进行递归计算。完成计算后,新值将存储在binomtable
中,以备下次使用。这种策略节省了很多浪费的计算工作,并且可以在这种递归算法的性能上产生巨大的差异。
关于您的具体问题
if v then return v end
意思是,如果变量v
不是nil
或false
,则返回v变量的值并停止执行该函数。
--Similar
function myfunc(input)
local MyVar = "I am a string and am not nil!"
if MyVar then
return "hi"
else
return "hello"
end
print("I am not seen because I am unreachable code!")
end
如果调用此函数,则由于MyVar为真,因为它具有值,所以它将始终返回“ hi”而不是“ hello”。下面的print
函数也永远不会被调用,因为它在调用return
之后会停止执行该函数。
现在对于您的代码情况,它正在检查table
,以查看它是否在某个index
处有一个条目,如果存在,则返回值。