grosse Zahlen - Unterschied Python2 und Python3

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
lagerschaden
User
Beiträge: 13
Registriert: Samstag 21. Oktober 2017, 11:34

Python kann ja mit sehr grossen Zahlen umgehen, aber da scheint es Unterschiede zwischen Python2 und Python3 zu geben. Das nachfolgende Beispiel läuft mit Python2 auch mit 6-stelligen Werten für p problemlos durch, während Python3 schon bei p=8 mit einer Fehlermeldung aufgibt.

Code: Alles auswählen

#!/usr/bin/python2
# -*- coding: utf-8 -*-

# berechnet die p-te Potenz von start durch Multiplikation 
# und rechnet durch Division wieder zurueck, Ergebnis muss
# dann gleich start sein

p = 8
start = 8648234678954023643289846329847304534823

sum = start

for i in range(p):
    sum = sum * start

for i in range(p):
    sum = sum / start

print(sum)
print(start)
Fehlermeldung:

Code: Alles auswählen

Traceback (most recent call last):
  File "./sum.py", line 17, in <module>
    sum = sum / start
OverflowError: integer division result too large for a float
nezzcarth
User
Beiträge: 1646
Registriert: Samstag 16. April 2011, 12:47

Der Traceback gibt schon einen ersten Hinweis, den du leicht im Interpreter überprüfen kannst:

Code: Alles auswählen

Python 3.7.4 (default, Jul 16 2019, 07:12:58) 
[GCC 9.1.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> 5/2
2.5
>>> 5//2
2

Code: Alles auswählen

Python 2.7.16 (default, Mar 11 2019, 18:59:25) 
[GCC 8.2.1 20181127] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> 5/2
2
>>> 5//2
2
>>> from __future__ import division
>>> 5/2
2.5
Übrigens existieren analog zur Inkrementierung 'i += 1' auch die Operatoren 'i /= 2' und 'i //= 2'.
lagerschaden
User
Beiträge: 13
Registriert: Samstag 21. Oktober 2017, 11:34

In dem obigen Beispiel ist sum während das Programmablaufes immer eine ganze Zahl, Python3 rechnet dann also bei der Division im Gegensatz zu Python2 nicht ganz korrekt, weil offensichtlich eine Umwandlung in float stattfindet.

Ich habe mal ein print(sum) eingefügt, dann rechnet Python3 bei der Multiplikation auch bei grossen Werten mit Integer und ab der 1. Division mit Float obwohl die Zahl immer eine ganze Zahl ist. Ist die Zahl zu gross, steigt Python3 mit der Fehlermeldung aus während Python2 das locker managed.

Hat das denn einen Vorteil, dass Python3 eine extra Integer-Division hat? Bei nicht zu grossen Zahlen macht Python3 es ja auch richtig.

Code: Alles auswählen

#!/usr/bin/python3
# -*- coding: utf-8 -*-

# berechnet die p-te Potenz von start durch Multiplikation 
# und rechnet durch Division wieder zurueck, Ergebnis muss
# dann gleich start sein

p = 999
start = 8648234678954023643289846329847304534823

sum = start

for i in range(p):
    sum = sum * start
    print(sum)

for i in range(p):
    sum = sum / start
    print(sum)

print(sum)
print(start)
Sirius3
User
Beiträge: 17819
Registriert: Sonntag 21. Oktober 2012, 17:20

Das hat den Vorteil, dass viele bei der Division erwarten, dass bei 3/2 das selbe Ergebnis kommt wie bei 3./2. Ganzzahldivision ist eine andere Operation und das Ergebnis sollte nicht vom Typ der Operanden abhängen.

Warum programmierst Du start**p nach und nennst das Ergebnis sum?
lagerschaden
User
Beiträge: 13
Registriert: Samstag 21. Oktober 2017, 11:34

Das bedeutet aber, dass gerade bei der aktuellen Umstellung auf Python3 vieles in die Hose geht (das genau ist mir passiert), weil das Verhalten der Division bei kleinen und grossen Zahlen unterschiedlich ist, wie man in meinem Beispiel sieht. Übrigens meckert 2to3 das nicht an, kann es auch nicht, da es nicht weiss, ob Integer oder Float bzw. die Zahlengrösse.

Die Bezeichnung sum stammt aus dem grösseren Projekt, da ist es auch eine Summe. Ich habe hier nur ein Snippet gezeigt.
Zuletzt geändert von lagerschaden am Sonntag 6. Oktober 2019, 10:05, insgesamt 1-mal geändert.
nezzcarth
User
Beiträge: 1646
Registriert: Samstag 16. April 2011, 12:47

lagerschaden hat geschrieben: Sonntag 6. Oktober 2019, 09:55 In dem obigen Beispiel ist sum während das Programmablaufes immer eine ganze Zahl, Python3 rechnet dann also bei der Division im Gegensatz zu Python2 nicht ganz korrekt, weil offensichtlich eine Umwandlung in float stattfindet.

Ich habe mal ein print(sum) eingefügt, dann rechnet Python3 bei der Multiplikation auch bei grossen Werten mit Integer und ab der 1. Division mit Float obwohl die Zahl immer eine ganze Zahl ist. Ist die Zahl zu gross, steigt Python3 mit der Fehlermeldung aus während Python2 das locker managed.
Wenn ich dich richtig verstehe, wäre dein Vorschlag, dass 4/2 einen Integer ergibt, weil das Ergebnis eine Ganzzahl ist, 4/3 aber einen Float? Das wäre aus meiner Sicht eine schlechte Lösung, da dann der Typ schlecht vorhersagbar ist. Die beiden denkbaren Alternativen sind, dass Division-Ergebnisse entweder konsistent Integer, oder konsistent Floats sind. Und in der Wahl dieser beiden Varianten unterscheiden sind Python2 und Python3. Ich kenne die Begründung der Python Entwickler für diese Design-Entscheidung nicht, aber aus meiner Sicht ist die Art und Weise, wie Python3 es handhabt sinnvoller, denn es geht nichts verloren. 4/3 ist für Python2 1 und wenn ich das in einen Float konvertiere, bleibt es 1.0. 4/2 Ist für Python3 2.0 und wenn ich es in einen Integer konvertiere ist es immer noch 2.
Zuletzt geändert von nezzcarth am Sonntag 6. Oktober 2019, 10:13, insgesamt 2-mal geändert.
Sirius3
User
Beiträge: 17819
Registriert: Sonntag 21. Oktober 2012, 17:20

@lagerschaden: welche Art der Division du brauchst hängt halt davon ab was du an der Stelle tun willst. Das kann man nur händisch an jeder Stelle im Code entscheiden. Zum Glück versteht python2 dank future-Import die neue Syntax und Du siehst schnell anhand Deiner Unit-Tests ob alles mit der neuen Syntax noch läuft.
lagerschaden
User
Beiträge: 13
Registriert: Samstag 21. Oktober 2017, 11:34

Dass 4/3 für Python2 nicht 1.333 sondern 1 ergibt, wissen wir ja aus der Erfahrung und haben das entsprechend berücksichtigt.

Das neue Verhalten von Python3 macht bei der Umstellung von 2 auf 3 aber grosse Probleme, ich habe an diesem Projekt mehrere Tage gebraucht, nur um diesen 1 Fehler zu finden. Ich werde also alte Projekte vermutlich gar nicht umstellen sondern nur neue Projekte mit Python3 beginnen.

Vielen Dank an Euch für die Hilfe.
nezzcarth
User
Beiträge: 1646
Registriert: Samstag 16. April 2011, 12:47

lagerschaden hat geschrieben: Sonntag 6. Oktober 2019, 10:12 Ich werde also alte Projekte vermutlich gar nicht umstellen sondern nur neue Projekte mit Python3 beginnen.
Dabei solltest du aber berücksichtigen, dass der Python2 Support Ende des Jahres ausläuft. Das bedeutet zwar natürlich nicht, dass der Python2 Interpreter unverzüglich die Arbeit verweigert, aber es wird zunehmend schwerer, ihn noch (zum Laufen) zu bekommen, da es keine offiziellen Versionen mehr geben wird. Er wird nach und nach aus den offiziellen Repositorien der Linux Distributionen verschwinden und auch auf zukünftigen Windows Versionen möglicherweise nicht mehr ausführbar sein. Software ohne (Sicherheits)updates ist ein Problem.
Antworten