これが何であるかについては、おそらく多くの説明は必要ありません。私の本当の問題は、プログラムの終了です。トレースされた戻り値と、値をステップ実行するためにメイン関数で使用しているネストされた for ループを出力しました。これが発生する理由はわかりませんが、ループを最後に通過してから実際に終了するまでに、プログラムがさらに約 10 分かかります。ループ インデックスは (事前チェックのために) 増加していますが、私の Ackermann 関数は明らかに余分な反復を実行していません (いずれにせよ実行したいわけではありません)。一方、唯一の論理的な説明は、ループが壊れていないということですが、もしそうなら、私のアッカーマン関数は新しい b 値を返すはずです。したがって、これについて私が考えることができる唯一の他の原因は、私のデータ構造をクリアしてメモリヒープをフラッシュするのに長いガベージコレクションを取ります。慣れていない人のために説明すると、ここでの考え方は、伝統的に非常に面倒な再帰関数として提示されていたものを反復関数として実装することです。再帰的に:
正の整数 m と n が与えられた場合: m = 0 の場合、n + 1 を返します。それ以外の場合、n = 0 の場合、Ackermann(m - 1, 1) を返します。それ以外の場合は Ackermann(m - 1, Ackermann(m, n - 1)) を返します。したがって、スタックを使用して再帰関数呼び出しをエミュレートし、ヒープからメモリを使用でき、実行時間を制限する呼び出しスタックのサイズに依存しないようにするというアイデアを繰り返します。計算が終了してから、プログラムがユーザーが正常に終了するポイントに到達するまでの間に、これらの長い遅延を引き起こしているフローの何かを見落としているのではないかと心配しています。
これが私のコードです:
static void Main(string[] args)
{
ulong i, j;
i = j = 0;
for (i = 1; i <= 3; i++)
for (j = 1; j <= 15; j++)
Console.WriteLine("[{0}] Ackermann({1},{2}) = {3}", DateTime.Now, i, j, Ackermann(i, j));
Console.WriteLine("Press any key to continue...");
Console.ReadKey();
}
static ulong Ackermann(ulong a, ulong b)
{
Stack<ulong> ackStack = new Stack<ulong>();
ackStack.Push(a);
while (ackStack.Count > 0)
{
a = ackStack.Pop();
if (a == 0)
b++;
else if (b == 0)
{
ackStack.Push(--a);
b = 1;
}
else
{
ackStack.Push(--a);
ackStack.Push(++a);
b--;
}
}
return b;
}
考え?補足として、これは c# ですが、この動作は MinGW でコンパイルされた C++ でも発生します。