我用C语言编写了一个程序,用于计算用户输入的2个非负整数的 Ackermann 值。该程序检查整数是否为非负数,如果是,则计算它们的Ackermann值,然后请求新的输入或退出。该程序在C语言中运行良好,我对此没有任何问题。这是我的代码:
int ackermann(int m, int n){
if (m == 0) return n + 1;
if (n == 0) return ackermann(m - 1, 1);
return ackermann(m - 1, ackermann(m, n - 1));
}
但是,实际上,出于大学类(class)的需要,我们使用了C的修改版本(基本上相同,但语法规则有所不同),它模拟了MIPS汇编语言的语法和规则。更具体地说,我们使用寄存器来操纵除数组和结构之外的所有数据。另外,我们不能使用for,while或do-while循环,而如果使用和转到语句,则使用。因此,我用这种语言编写了以下程序(正如我所说的,只是语法不同的C而已)。我的问题是,它仅适用于(x,0)和(0,y)用户输入(x和y是非负数)。它不适用于(4,1),(3,2)以及通常所有不为零的输入。我知道由于大量的计算,它无法有效地工作于(10,10)之类的非常大的数字。但是我希望它能用于一些简单的输入,例如Ackermann(3,1)==13。有关Ackermann函数的更多信息,请参见:http://en.wikipedia.org/wiki/Ackermann_function
这是我的代码:
//Registers --- The basic difference from C is that we use registers to manipulate data
int R0=0,R1,R2,R3,R4,R5,R6,R7,R8,R9,R10,R11,R12,R13,R14,R15,R16,R17,R18,R19,R20,R21,
R22,R23,R24,R25,R26,R27,R28,R29,R30,R31;
int ackermann(int m, int n){
R4 = m;
R5 = n;
if(R4 != 0)
goto outer_else;
R6 = R5 + 1;
return R6;
outer_else:
if(R5 != 0)
goto inner_else;
R7 = R4 - 1;
R6 = ackermann(R7, 1);
return R6;
inner_else:
R8 = R5 - 1;
R9 = ackermann(R4, R8);
R10 = R4 - 1;
R6 = ackermann(R10, R9);
return R6;
}
最佳答案
我认为您的问题是这些寄存器值被定义为全局变量,并且正在通过内部调用ackermann()
进行更新,而外部调用则取决于这些值是否不变。例如,看看您的inner_else
的注册版本中的ackermann()
子句:它调用ackermann(R4, R8)
,在下一条语句中取决于R4的当前值,但递归调用在到达赋值语句之前更改R4的设置。
两种常见的解决方案:
ackermann()
函数时,手动保存所有寄存器的状态,然后在退出时将其恢复。 尽管解决方案1更简单,但我怀疑您的老师可能更喜欢解决方案2,因为它说明了编译器在其生成的汇编代码中用于处理实际寄存器管理的一种技术。