递归 Lua 函数中循环和条件的优化
Optimization of Loops and conditionals in Recursive Lua Function
The following is the code of my function
function myfunction ( ... )
local tbl = table.pack(...)
for _, v in ipairs(tbl) do
if type(v) ~= 'number' then
print('Error: Something different is expected.')
return
elseif v~= math.abs(v) then
print('Error: Your input needs slight modification.')
return
end
end
if some condition then
**recursive call to myfunction**
else
some result
end
end
该功能运行良好,并为我提供了预期的结果。但是可以观察到函数以递归方式调用自身的问题。因此,我在下面给出的代码的第一部分在每次递归调用期间也会重复多次。显然我只想检查一次输入,如果输入不正确则退出函数。如果输入正确,则不应在每次递归调用时都检查它。那么如何为此目的优化代码。是否可以将某个值分配给全局变量,然后在函数内部的某处使用它(在 if else 条件下)以避免重复。但是再次检查价值将得到重复(尽管与当前方法相比成本更低。问题是避免重复以下代码(这是上面代码的一部分)。
for _, v in ipairs(tbl) do
if type(v) ~= 'number' then
print('Error: Something different is expected.')
return
elseif v~= math.abs(v) then
print('Error: Your input needs slightly modified')
return
end
end
例如,考虑以下函数。
function factorial(n)
if (n == 0) then
return 1
else
return n * factorial(n - 1)
end
end
当执行factorial(9.3)
时,由于不涉及错误输入检查,它会导致堆栈溢出。为了处理这个问题,添加了以下错误机制。
function factorialwithinputcheck(n)
if type(n) ~= 'number' then
error('only numbers are expected')
return
elseif n~= math.floor(n) or n~=math.abs(n) then
error('only positive integers are expected')
return
end
if (n == 0) then
return 1
else
return n * factorialwithinputcheck(n-1)
end
end
此函数会在输入不正确时给出错误并停止执行。 factorialwithinputcheck(9.3)
不会导致堆栈溢出。但是再次在每次递归调用中进行输入检查。如何优化此代码?
在我的评论中更具体,我建议这样:
function _factorial(n)
if (n == 0) then
return 1
else
return n * _factorial(n-1)
end
end
function factorialwithinputcheck(n)
if type(n) ~= 'number' then
error('only numbers are expected')
return
elseif n~= math.floor(n) or n~=math.abs(n) then
error('only positive integers are expected')
return
end
if (n == 0) then
return 1
else
return n * _factorial(n-1)
end
end
或隐藏_factorial
:
function factorialwithinputcheck(n)
local function _factorial(n)
if (n == 0) then
return 1
else
return n * _factorial(n-1)
end
end
if type(n) ~= 'number' then
error('only numbers are expected')
return
elseif n~= math.floor(n) or n~=math.abs(n) then
error('only positive integers are expected')
return
end
if (n == 0) then
return 1
else
return n * _factorial(n-1)
end
end
但同样,我不完全确定这种方式是否必须多次“创建”_factorial
函数(这也会对性能产生影响)。但也许这可以通过一些基准测试来解决。
编辑:哦,如果你想要一些输入净化:到目前为止,你不检查负数。
Edit2:并且由于您要求对阶乘函数进行一般优化。是的,当然可以将递归过程转换为迭代过程(避免多次创建新的堆栈帧)。
使用某种 累加器 (acc
) 将 n*acc
传递给下一个调用,您也可以使函数尾部递归,(根据到 this pil chapter(我希望在更频繁的 lua 版本中没有变化)lua 将为您处理)。
例如:
local function factorial_rec(n)
local function _factorial(n)
if (n == 0) then
return 1
else
return n * _factorial(n-1)
end
end
if type(n) ~= 'number' then
error('only numbers are expected')
return
elseif n~= math.floor(n) or n~=math.abs(n) then
error('only positive integers are expected')
return
end
if (n == 0) then
return 1
else
return n * _factorial(n-1)
end
end
(但老实说,如果我从 0 到 40 遍历 factorial
,我看不出有多少性能提升(0.000293
s vs 0.000354
s,以 21!
开头的数字已经超出 lua 中的数字范围(对于我的安装),仅使用非常基本的基准进行检查))
The following is the code of my function
function myfunction ( ... )
local tbl = table.pack(...)
for _, v in ipairs(tbl) do
if type(v) ~= 'number' then
print('Error: Something different is expected.')
return
elseif v~= math.abs(v) then
print('Error: Your input needs slight modification.')
return
end
end
if some condition then
**recursive call to myfunction**
else
some result
end
end
该功能运行良好,并为我提供了预期的结果。但是可以观察到函数以递归方式调用自身的问题。因此,我在下面给出的代码的第一部分在每次递归调用期间也会重复多次。显然我只想检查一次输入,如果输入不正确则退出函数。如果输入正确,则不应在每次递归调用时都检查它。那么如何为此目的优化代码。是否可以将某个值分配给全局变量,然后在函数内部的某处使用它(在 if else 条件下)以避免重复。但是再次检查价值将得到重复(尽管与当前方法相比成本更低。问题是避免重复以下代码(这是上面代码的一部分)。
for _, v in ipairs(tbl) do
if type(v) ~= 'number' then
print('Error: Something different is expected.')
return
elseif v~= math.abs(v) then
print('Error: Your input needs slightly modified')
return
end
end
例如,考虑以下函数。
function factorial(n)
if (n == 0) then
return 1
else
return n * factorial(n - 1)
end
end
当执行factorial(9.3)
时,由于不涉及错误输入检查,它会导致堆栈溢出。为了处理这个问题,添加了以下错误机制。
function factorialwithinputcheck(n)
if type(n) ~= 'number' then
error('only numbers are expected')
return
elseif n~= math.floor(n) or n~=math.abs(n) then
error('only positive integers are expected')
return
end
if (n == 0) then
return 1
else
return n * factorialwithinputcheck(n-1)
end
end
此函数会在输入不正确时给出错误并停止执行。 factorialwithinputcheck(9.3)
不会导致堆栈溢出。但是再次在每次递归调用中进行输入检查。如何优化此代码?
在我的评论中更具体,我建议这样:
function _factorial(n)
if (n == 0) then
return 1
else
return n * _factorial(n-1)
end
end
function factorialwithinputcheck(n)
if type(n) ~= 'number' then
error('only numbers are expected')
return
elseif n~= math.floor(n) or n~=math.abs(n) then
error('only positive integers are expected')
return
end
if (n == 0) then
return 1
else
return n * _factorial(n-1)
end
end
或隐藏_factorial
:
function factorialwithinputcheck(n)
local function _factorial(n)
if (n == 0) then
return 1
else
return n * _factorial(n-1)
end
end
if type(n) ~= 'number' then
error('only numbers are expected')
return
elseif n~= math.floor(n) or n~=math.abs(n) then
error('only positive integers are expected')
return
end
if (n == 0) then
return 1
else
return n * _factorial(n-1)
end
end
但同样,我不完全确定这种方式是否必须多次“创建”_factorial
函数(这也会对性能产生影响)。但也许这可以通过一些基准测试来解决。
编辑:哦,如果你想要一些输入净化:到目前为止,你不检查负数。
Edit2:并且由于您要求对阶乘函数进行一般优化。是的,当然可以将递归过程转换为迭代过程(避免多次创建新的堆栈帧)。
使用某种 累加器 (acc
) 将 n*acc
传递给下一个调用,您也可以使函数尾部递归,(根据到 this pil chapter(我希望在更频繁的 lua 版本中没有变化)lua 将为您处理)。
例如:
local function factorial_rec(n)
local function _factorial(n)
if (n == 0) then
return 1
else
return n * _factorial(n-1)
end
end
if type(n) ~= 'number' then
error('only numbers are expected')
return
elseif n~= math.floor(n) or n~=math.abs(n) then
error('only positive integers are expected')
return
end
if (n == 0) then
return 1
else
return n * _factorial(n-1)
end
end
(但老实说,如果我从 0 到 40 遍历 factorial
,我看不出有多少性能提升(0.000293
s vs 0.000354
s,以 21!
开头的数字已经超出 lua 中的数字范围(对于我的安装),仅使用非常基本的基准进行检查))