这个递归Windows CMD脚本有什么问题?它赢了';我不能正确地对待阿克曼

这个递归Windows CMD脚本有什么问题?它赢了';我不能正确地对待阿克曼,windows,command-line,recursion,batch-file,cmd,Windows,Command Line,Recursion,Batch File,Cmd,我想计算一下阿克曼函数。关于我努力实现的目标的描述,请参见 使用测试脚本,测试04给出了正确的5。然而,测试14给出的是5而不是6,测试24给出的是5而不是11 我哪里做错了 ::echo off set depth=0 :ack if %1==0 goto m0 if %2==0 goto n0 :else set /a n=%2-1 set /a depth+=1 call :ack %1 %n% set t=%errorlevel% set /a depth-=1 set /a m=%1

我想计算一下阿克曼函数。关于我努力实现的目标的描述,请参见

使用测试脚本,测试04给出了正确的5。然而,测试14给出的是5而不是6,测试24给出的是5而不是11

我哪里做错了

::echo off
set depth=0
:ack
if %1==0 goto m0
if %2==0 goto n0

:else
set /a n=%2-1
set /a depth+=1
call :ack %1 %n%
set t=%errorlevel%
set /a depth-=1
set /a m=%1-1
set /a depth+=1
call :ack %m% %t%
set t=%errorlevel%
set /a depth-=1
if %depth%==0 ( exit %t% ) else ( exit /b %t% )

:m0
set/a n=%2+1
if %depth%==0 ( exit %n% ) else ( exit /b %n% )

:n0
set /a m=%1-1
set /a depth+=1
call :ack %m% %2
set t=%errorlevel%
set /a depth-=1
if %depth%==0 ( exit %t% ) else ( exit /b %t% )
我使用这个脚本来测试它

@echo off
cmd/c ackermann.cmd %1 %2
echo Ackermann of %1 %2 is %errorlevel%
测试1的样本输出给出:

>test 1 1
>set depth=0
>if 1 == 0 goto m0
>if 1 == 0 goto n0
>set /a n=1-1
>set /a depth+=1
>call :ack 1 0
>if 1 == 0 goto m0
>if 0 == 0 goto n0
>set /a m=1-1
>set /a depth+=1
>call :ack 0 0
>if 0 == 0 goto m0
>set/a n=0+1
>if 2 == 0 (exit 1  )  else (exit /b 1  )
>set t=1
>set /a depth-=1
>if 1 == 0 (exit 1  )  else (exit /b 1  )
>set t=1
>set /a depth-=1
>set /a m=1-1
>set /a depth+=1
>call :ack 0 1
>if 0 == 0 goto m0
>set/a n=1+1
>if 1 == 0 (exit 2  )  else (exit /b 2  )
>set t=2
>set /a depth-=1
>if 0 == 0 (exit 2  )  else (exit /b 2  )
Ackermann of 1 1 is 2

变量m和n的范围是什么


在一次对:ack的调用中设置值,然后递归地再次调用,设置值。你会覆盖它们吗?在基于堆栈的语言(如C和Java)中,局部变量很好,每一级递归都会得到新的变量。cmd中发生了什么?

将上面的第27行从

call :ack %m% %2 


我们中的一些人可能不知道什么是“阿克曼”。你说这“几乎”行得通。那么到底是什么问题呢?这里有跟踪,在执行路径的什么点上,事情会偏离预期吗?这里没有范围问题。它总是使用子例程或返回代码的参数,因此在递归调用之前不存在变量被设置,然后再次使用的地方(除了
depth
,但这是有意的)。@Johannes:是的,你是对的。我在寻找变量m和n,但它们是暂时的。(脸红)这也是一件简单的事情。哦,好吧,这是成功的解决方案。非常感谢,帕特里克。
call :ack %m% 1