递归LUA功能中的环和条件优化

发布于 2025-01-18 19:24:27 字数 1585 浏览 0 评论 0原文

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

该功能正常工作,并给我带来了预期的结果。但是,问题可以观察到该功能以递归方式自称。因此,我下面提供的代码的第一部分在每个递归电话中也会重复几次。显然,我只想检查一次输入,如果功能不正确,则退出该函数。如果输入正确,则不应将其检查每个递归调用。因此,如何为此目的对代码进行优化。可以将某些值分配给全局变量,然后在功能内(如果在其他情况下)将其使用以避免重复。但是再次,对值的支票将重复重复(尽管与当前方法相比,它的成本较低。问题是避免重复以下代码(这是上述代码的一部分)。

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

时 。 cattorial(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

机制代码> fortorialWithInputCheck(9.3)未导致堆栈溢出。

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

The function works fine and it gives expected results to me. But the problem as one can observe that function is calling itself in recursive manner. So the first part of the code which I am giving below also gets repeated several times during each recursive call. Obviously I want to check input only once and exit the function if it is incorrect. If input is correct, then it should not be checked every recursive call. So how the code can be optimized for this purpose. Can some value be assigned to global variable and then use it somewhere inside the function (in if else condition) to avoid repetition. But again the check for value will get repeat (though it is less costly compared to the current approach. The problem is to avoid repetition of the following code (which is part of above code).

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

As an example, consider the following function.

function factorial(n)
    if (n == 0) then
        return 1
    else
        return n * factorial(n - 1)
    end
end

When factorial(9.3) is executed it results into stack overflow as no error input check is involved. To handle this the following error mechanism is added.

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

This function gives error and stops execution whenever input is incorrect. The factorialwithinputcheck(9.3) doesn't result into stack overflow. But again the input check is made in every recursive call. How this code for example can be optimised?

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

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

发布评论

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

评论(1

清醇 2025-01-25 19:24:27

正如我的评论中更具体,我建议这样:

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传递给下一个调用,您也可以使函数尾部递归,(根据到这个pil章节(我希望在更频繁的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.000293s vs 0.000354s) code> 形式 0 到 40,以 21! 开头的数字已经超出了 lua 中数字的范围(对于我的安装),仅使用非常基本的基准进行检查))

Being more specific as in my comment, I'd propose something like this:

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

or hiding _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

but again, I'm not completely sure if this way the _factorial function has to be "created" multiple times (which should have a performance impact as well). But maybe this can be figured out with some benchmarking.

EDIT: Oh and if you want some input sanitizing: Up to now, you don't check for negative numbers.

Edit2: And since you ask for general optimization of your factorial function. Yes of course one could convert the recursive procedure into an iterative one (avoiding creating new stack frames that many times).

Using some sort of accumulator (acc) passing n*acc down to the next call, you could alternatively make the function tail recursive, (according to this pil chapter (I hope there is no change in that in more frequent lua verions) lua will then handle this for you).
For example:

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

(but to be honest I don't see much of a performance boost with this (0.000293s vs 0.000354s if I loop over factorial form 0 to 40, numbers starting with 21! are already beyond the range for numbers in lua (for my installation), checked only with a very rudimentary benchmark))

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