Seite 1 von 1

Iterieren bis 49*48*47*46*45*44

Verfasst: Montag 23. Oktober 2006, 09:40
von murphy
hi!

Python kennt ja große zahlen:

Code: Alles auswählen

>>> 49*48*47*46*45*44
10068347520L
nun wollte ich gerne so oft eine berechnung ausführen; for i in range(...) schien mir das richtige mittel:

Code: Alles auswählen

>>> for i in range(49*48*47*46*45*44):
...   pass
... 
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
OverflowError: range() result has too many items
geht also nicht - klar, range erzeugt ja eine liste, und die wäre zu groß. also nehme ich xrange:

Code: Alles auswählen

>>> for i in xrange(49*48*47*46*45*44):
...   pass
... 
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
OverflowError: long int too large to convert to int
Python mag mich nicht ^^

wie krieg ich das hin? ich weiß, dass die schleife lange laufen wird, aber es sollte doch möglich sein, das ohne while zu machen.

ps: es geht natürlich um eine dieser "6 aus 49"-matheaufgaben aus der uni.

Verfasst: Montag 23. Oktober 2006, 09:58
von BlackJack
Da wirst Du wohl nicht um ``while`` herumkommen. Du kannst die Schleife aber in einer Funktion verstecken:

Code: Alles auswählen

def xxrange(n):
    i = 0
    while i < n:
        yield i
        i += 1
Dir ist schon klar das man diese Uni-Lotto-Aufgaben auch ohne "brute-force" Programme lösen kann? Das ist eigentlich der Sinn dieser Aufgaben. :-)

edit: Wenn eine Iteration eine Millisekunde dauert, dann wartest Du auch nur 116 Tage auf das Ergebnis. :-D

Verfasst: Montag 23. Oktober 2006, 11:47
von Leonidas
Milan hat auch schon mal xrange in Python implementiert, so dass es auch mit Longs auskommt. Ich finde es momentan zwar nicht (ihh, Internet-Stehplatz mit Sitekiosk) aber du solltest mit dem Stichwort xlrange etwas brauchbares finden können.

Verfasst: Donnerstag 26. Oktober 2006, 21:19
von Joghurt
murphy, dir ist bewusst, dass selbst wenn Python 10000 Schleifendurchläufe pro Sekunde schafft, es über 11 Stunden dauert, bis es durch ist?

Verfasst: Samstag 28. Oktober 2006, 10:23
von mitsuhiko
Du könntest count() dafür verwenden:

Code: Alles auswählen

from itertools import count
max = 49*48*47*46*45*44
for i in count():
 if i == max:
  break
 print "foo"
Aber für was brauchst du so große Zahlen? Oo

Verfasst: Samstag 28. Oktober 2006, 11:20
von BlackJack
Bis Python 2.4 kannst Du `count()` nicht benutzen:

Code: Alles auswählen

In [11]: a = itertools.count(sys.maxint)

In [12]: a.next()
Out[12]: 2147483647

In [13]: a.next()
Out[13]: -2147483648
In Python 2.5 ist diese nette Überraschung korrigiert worden. :-)

Verfasst: Samstag 28. Oktober 2006, 14:34
von birkenfeld
Stimmt nicht:

Code: Alles auswählen

>>> x = itertools.count(-1)
>>> x.next()
4294967295L
>>> x.next()
0
>>> x.next()
1
Das ist ein Bug in 2.5. In 2.5.1 wird count() wieder wie in 2.4 korrekt mit negativen counts funktionieren und bei sys.maxint wrappen.

Dass count() nur den Bereich von native ints abdeckt, ist laut Raymond so gewollt.

Verfasst: Samstag 28. Oktober 2006, 15:43
von BlackJack
Was ist denn das für ein Schwachsinn. Das läuft total den Erwartungen nach der `int()`/`long()` Vereinheitlichung entgegen und ist ziemlich low-level und plattformabhängig. Irgendwie unpythonisch.

Wo hat Hettinger das denn gesagt und eventuell begründet? Gibt's 'ne Referenz?

Verfasst: Samstag 28. Oktober 2006, 17:08
von birkenfeld
Ich habe das verwechselt. Er hat es nicht als gewollt bezeichnet, sondern sagte in einem feature request:
It's not a bug -- it is the documented behavior.
The simple work-around is to roll your own generators:
[...]
Will look at possibly enhancing this for Py2.5.
Er ist aber nicht dazugekommen :)