所以我尝试创建基本Ackermann函数的修改版本,该函数使用字典来存储已经计算的值,这样下次当程序遇到类似的函数调用时,它可以使用已经计算的值,这个似乎大大加快了这个过程。这是代码:
import sys
sys.setrecursionlimit(100000)
resultset ={}
def ackermann(m, n):
"""Computes the Ackermann function A(m, n)
See http://en.wikipedia.org/wiki/Ackermann_function
n, m: non-negative integers
"""
if (m,n) in resultset:
return resultset[(m,n)]
if m == 0:
ans = n+1;
elif n == 0:
ans = ackermann(m-1, 1)
else:
ans = ackermann(m-1, ackermann(m, n-1))
if m != 0:
resultset[(m,n)] = ans
return ans;
for i in range(0,10) :
for j in range(0,10) :
print("ackermann(%d, %d): " % (i, j) + str(ackermann(i,j)))
现在我遇到的问题是它会在很短的时间后停止执行。输出如下:
ackermann(0, 0): 1
ackermann(0, 1): 2
ackermann(0, 2): 3
ackermann(0, 3): 4
ackermann(0, 4): 5
ackermann(0, 5): 6
...
...
...
ackermann(3, 2): 29
ackermann(3, 3): 61
ackermann(3, 4): 125
ackermann(3, 5): 253
ackermann(3, 6): 509
ackermann(3, 7): 1021
ackermann(3, 8): 2045
ackermann(3, 9): 4093
ackermann(4, 0): 13
ackermann(4, 1): 65533
Segmentation fault
我的系统是核心i5,有12 GB的内存,这个程序在达到内存限制之前退出,可能是什么问题?
我还尝试使用Shelves而不是字典,以便将数据存储在磁盘上。这是代码:
我也尝试使用书架而不是字典,以便我可以在磁盘上看到用法。这是代码..
import sys
sys.setrecursionlimit(100000)
import shelve
resultset = shelve.open("file.o")
def ackermann(m, n):
"""Computes the Ackermann function A(m, n)
See http://en.wikipedia.org/wiki/Ackermann_function
n, m: non-negative integers
"""
if str((m,n)) in resultset:
return resultset[str((m,n))]
if m == 0:
ans = n+1;
elif n == 0:
ans = ackermann(m-1, 1)
else:
ans = ackermann(m-1, ackermann(m, n-1))
if m != 0:
resultset[str((m,n))] = ans
return ans;
for i in range(0,6) :
for j in range(0,6) :
print("ackermann(%d, %d): " % (i, j) + str(ackermann(i,j)))
输出文件正好达到6MB并且python崩溃了。有人知道为什么?
答案 0 :(得分:2)
很多试验和错误,我能够理解问题是程序由于递归而耗尽了堆栈空间。通过将堆栈大小设置为无限,我能够在Linux上修复此问题。不幸的是,我不认为在Windows上有类似的解决方案。这是我做的代码..
import resource, sys
resource.setrlimit(resource.RLIMIT_STACK, (resource.RLIM_INFINITY, resource.RLIM_INFINITY))
sys.setrecursionlimit(10**8)
resultset ={}
def ackermann(m, n):
"""Computes the Ackermann function A(m, n)
See http://en.wikipedia.org/wiki/Ackermann_function
n, m: non-negative integers
"""
if (m,n) in resultset:
return resultset[(m,n)]
if m == 0:
ans = n+1;
elif n == 0:
ans = ackermann(m-1, 1)
else:
ans = ackermann(m-1, ackermann(m, n-1))
if m != 0:
resultset[(m,n)] = ans
return ans;
for i in range(0,6) :
for j in range(0,6) :
print("ackermann(%d, %d): " % (i, j) + str(ackermann(i,j)))
这两行是魔术发生的地方:
resource.setrlimit(resource.RLIMIT_STACK,(resource.RLIM_INFINITY,resource.RLIM_INFINITY))sys.setrecursionlimit(10 ** 8)
无论如何,谢谢你的尝试。 :)
答案 1 :(得分:1)
Ackermann函数非常大,非常快......下一步(4,2)的值是2.00352993040684646497907235156025575044782547556975141 ...×10 ^ 19728。
如果你看一下segfault,你可能会得到这样的东西:
python[4413]: segfault at 7fff2bae5ff8 ip 000000000052185f sp 00007fff2bae6000 error 6 in python2.7[400000+2bd000]
错误6表示页面写入失败。