2016-02-21 25 views
10

Unter der Annahme, dass der Computer dieses Programm hat eine unendliche Menge an Speicher laufen, ich bin daran interessiert, wo Python brechen wird, wenn die folgenden ausgeführt wird:Welche technischen Einschränkungen verhindern die Berechnung der Graham-Zahl in Python?

Für Spaß, implementiert ich hyperoperators in Python als Modul hyperop. Einer meiner Beispiele ist die Nummer Graham:

def GrahamsNumber(): 
    # This may take awhile... 
    g = 4 
    for n in range(1,64+1): 
     g = hyperop(g+2)(3,3) 
    return g 

Die verkürzte Version der Klasse hyperop wie folgt aussieht:

def __init__(self, n): 
    self.n = n 
    self.lower = hyperop(n - 1) 

def _repeat(self, a, b): 
    if self.n == 1: 
     yield a 

    i = 1 
    while True: 
     yield a 
     if i == b: 
      break 
     i += 1 

def __call__(self, a, b): 
    return reduce(lambda x, y: self.lower(y, x), self._repeat(a, b)) 

Im Wesentlichen ist die Bibliothek nur eine rekursive fold rechten Betrieb mit einer speziellen Definition für die base case of n=1. Ursprünglich war __call__ schön golfed wie:

return reduce(lambda x, y: self.lower(y, x), [a,]*b) 

jedoch it turns out that you can't make a list with more elements than the size of a C long. Das war eine lustige Einschränkung, der die meisten Python-Programmierer wahrscheinlich in ihrem normalen Alltag nicht begegnen und die folgende Frage inspirierten.

Wo, wenn über wird die hyperop Berechnung nicht mehr aufgrund einer technischen Beschränkung von Python (speziell 2.7.10)?

+5

Als * "das beobachtbare Universum ist viel zu klein, um eine gewöhnliche digitale Darstellung von Grahams Zahl zu enthalten" *, werde ich nein sagen. Top-Tipp: Wenn du mit * anfangen musst "das ist eine legitime Frage" * hast du wahrscheinlich Unrecht! – jonrsharpe

+0

Ist die Frage nach der Verwendung von "yield" und "infinite sequences", oder etwas, das prägnanter gefasst werden kann? – user2864740

+0

Die Beschränkung auf mehr Elemente als die Größe eines C-Long wird nur für Python 2 erwähnt. – PascalVKooten

Antwort

1

Vielleicht Originalversion von hyperop ist robust und nicht wegen irgendeines esoterischen Ursache, aber diese genauen Code schlägt fehl, da hyperop Konstruktor selbst nennt und es stellt sich Runtime mit „maximale Rekursionstiefe überschritten“ (nach sys.setrecursionlimit der rekursiven Aufrufe - Das ist wahrscheinlich standardmäßig in 2.7.10 1000).