Python: Gibt es eine Möglichkeit, eine automatische Umwandlung von int zu lange int zu halten?

Python ist stärker typisiert als andere Skriptsprachen. Zum Beispiel in Perl:

perl -E '$c=5; $d="6"; say $c+$d' #prints 11 

Aber in Python:

 >>> c="6" >>> d=5 >>> print c+d Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: cannot concatenate 'str' and 'int' objects 

Perl wird einen String untersuchen und in eine Zahl umwandeln, und die Operatoren + - / * ** funktionieren wie erwartet mit einer Nummer. PHP ist ähnlich.

Python verwendet + um Strings zu verketten, so dass die versuchte Operation von c+d fehlschlägt, weil c ein String ist, d ein int. Python hat einen stärkeren Sinn für numerische Typen als Perl. OK – das kann ich damit umgehen.

Aber bedenke:

 >>> from sys import maxint >>> type(maxint) <type 'int'> >>> print maxint 9223372036854775807 >>> type(maxint+2) <type 'long'> >>> print maxint+2 9223372036854775809 >>> type((maxint+2)+maxint) <type 'long'> >>> print ((maxint+2)+maxint) 18446744073709551616 

Nun wird Python aus einer int, die in diesem Fall ist ein 64-Bit lang (OS X, Python 2.6.1) zu einem Python lange int, die von willkürlicher Präzision ist autopromotieren. Obwohl die Typen nicht gleich sind, sind sie ähnlich und Python erlaubt es, die üblichen numerischen Operatoren zu verwenden. Normalerweise ist das hilfreich. Es ist hilfreich bei der Glättung der Unterschiede zwischen 32 Bit und 64 Bit zum Beispiel.

Die Umwandlung von int nach long ist ein Weg:

 >>> type((maxint+2)-2) <type 'long'> 

Sobald die Umwandlung erfolgt ist, werden alle Operationen auf dieser Variablen nun in beliebiger Präzision durchgeführt. Die willkürlichen Präzisionsoperationen sind Größenordnungen langsamer als die nativen int-Operationen. Auf einem Drehbuch, an dem ich arbeite, würde ich irgendeine Hinrichtung haben, bissig und andere, die sich in Stunden verlängert haben. Erwägen:

 >>> print maxint**maxint # execution so long it is essentially a crash 

Also meine Frage: Gibt es einen Weg zu besiegen oder nicht erlauben die Auto-Förderung eines Python int zu einem Python long ?

Bearbeiten, Follow-up:

Ich erhielt mehrere Kommentare in Form von "warum auf der Erde würden Sie wollen C Stil Überlauf Verhalten?" Das Problem war, dass dieses besondere Stück Code OK auf 32 Bits in C und Perl (mit use int ) mit C's Überlaufverhalten funktionierte. Es gab einen fehlgeschlagenen Versuch, diesen Code an Python zu portieren. Pythons unterschiedliches Überlaufverhalten erweist sich als Teil des Problems. Der Code hat viele dieser verschiedenen Idiome (C, Perl, einige Python) gemischt (und diese Kommentare gemischt), so war es schwierig.

Im wesentlichen handelt es sich bei der Bildanalyse um ein scheibenbasiertes Hochpaßfilter, um einen ähnlichen Bildvergleich durchzuführen. Ein Teil des Hochpassfilters hat eine ganzzahlige Multiplikation von zwei großen Polynomen. Der Überlauf war im Wesentlichen ein "Do not-Care, es ist groß …" Art von Logik so das Ergebnis war wie beabsichtigt mit einem C-basierten Überlauf. So war die Verwendung von Horners Herrschaft mit O (n 2 ) Zeit eine Verschwendung, da die größeren Polynome nur "groß" wären – eine grob-gerechte Form der Carot-Top-Sättigungsarithmetik.

Das Ändern der Loop-basierten Polynom-Multiplikation auf eine Form von FFT ist wahrscheinlich wesentlich schneller. FFT läuft in der Nähe der linearen Zeit vs O (n 2 ) für Horners Regelpolynom multiplizieren. Das Gehen von der Scheibe, die auf in-Gedächtnis basiert, beschleunigt dieses auch. Die Bilder sind nicht schrecklich groß, aber der ursprüngliche Code wurde zu einer Zeit geschrieben, als sie als "riesig" angesehen wurden. Der Code-Besitzer ist nicht ganz bereit, seinen geliebten Code abzufüllen, also werden wir sehen. Die "richtige Antwort" für ihn ist wohl nur Perl oder C, wenn er diesen Code will.

Danke für die Antworten. Ich wusste nicht über das Dezimalmodul von Python, und das schien am nächsten zu sein, was ich fragte – auch wenn es in diesem Fall noch andere Probleme zu lösen gibt!

6 Solutions collect form web for “Python: Gibt es eine Möglichkeit, eine automatische Umwandlung von int zu lange int zu halten?”

Also willst du den einen wahren Weg wegwerfen und auf Überläufe zurückgehen. Dumm du

Es gibt keinen guten Aufstieg zum C / C ++ / C # / Java-Stil des Überlaufs. Es hebt nicht zuverlässig einen Fehlerzustand an . Für C und C99 ist es "undefiniertes Verhalten" in ANSI und POSIX (C ++ Mandate modulo return) und es ist ein bekanntes Sicherheitsrisiko. Warum willst du das?

Die Python-Methode von nahtlos überfließt zu einem langen ist der bessere Weg. Ich glaube, das ist das gleiche Verhalten, das von Perl 6 angepasst wird.

Sie können das Dezimal-Modul verwenden , um endlichere Überläufe zu erhalten:

 >>> from decimal import * >>> from sys import maxint >>> getcontext() Context(prec=28, rounding=ROUND_HALF_EVEN, Emin=-999999999, Emax=999999999, capitals=1, flags=[], traps=[DivisionByZero, Overflow, InvalidOperation]) >>> d=Decimal(maxint) >>> d Decimal('9223372036854775807') >>> e=Decimal(maxint) >>> f=d**e Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/decimal.py", line 2225, in __pow__ ans = ans._fix(context) File "/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/decimal.py", line 1589, in _fix return context._raise_error(Overflow, 'above Emax', self._sign) File "/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/decimal.py", line 3680, in _raise_error raise error(explanation) decimal.Overflow: above Emax 

Sie können Ihre Präzisions- und Randbedingungen mit Dezimalklassen festlegen und der Überlauf ist fast sofort. Sie können festlegen, was Sie fangen. Sie können Ihre max und min einstellen. Wirklich – Wie wird es besser als das? (Ich weiß nicht über die relative Geschwindigkeit, um ehrlich zu sein, aber ich vermute, es ist schneller als numby aber langsamer als native Ints offensichtlich …)

Für Ihre spezifische Frage der Bildverarbeitung klingt das wie eine natürliche Anwendung, um eine Form der Sättigungsarithmetik zu betrachten. Sie könnten auch betrachten, wenn Sie Überläufe auf 32 Arithmetik haben, überprüfen Sie Operanden auf dem Weg auf offensichtliche Fälle: pow, **, *. Sie könnten überladene Betreiber betrachten und auf die Bedingungen überprüfen, die Sie nicht wollen.

Wenn Dezimal-, Sättigungs- oder überladene Operatoren nicht funktionieren , können Sie eine Erweiterung schreiben . Der Himmel hilft dir, wenn du den Python-Weg des Überlaufs herauswerfen willst …

Wenn Sie möchten, dass arithmetische Überläufe innerhalb von zB 32 Bits überlaufen, können Sie zB numpy.uint32 .

Das gibt Ihnen eine Warnung, wenn ein Überlauf auftritt.

 >>> import numpy >>> numpy.uint32(2**32-3) + numpy.uint32(5) Warning: overflow encountered in ulong_scalars 2 

Ich habe zwar seine Geschwindigkeit getestet:

 >\python26\python.exe -m timeit "2**16 + 2**2" 1000000 loops, best of 3: 0.118 usec per loop >\python26\python.exe -m timeit "2**67 + 2**65" 1000000 loops, best of 3: 0.234 usec per loop >\python26\python.exe -m timeit -s "import numpy; numpy.seterr('ignore')" "numpy.uint32(2)**numpy.uint32(67) + numpy.uint32(2)**numpy.uint32(65)" 10000 loops, best of 3: 34.7 usec per loop 

Es sieht nicht gut aus.

Int vs lang ist ein historisches Erbe – in python 3 ist jeder int ein "lang". Wenn Ihr Skript Geschwindigkeit durch int Berechnung begrenzt ist, ist es wahrscheinlich, dass Sie es falsch machen.

Um Ihnen eine richtige Antwort zu geben, brauchen wir mehr Informationen darüber, was Sie versuchen zu tun.

Sie können Ihre Werte erzwingen, um zu normalem int wenn Sie eine num = int(num) gelegentlich in Ihrem Algorithmus einschließen. Wenn der Wert lang ist, aber in eine native int passt, wird es bis hinunter zu int. Wenn der Wert nicht in eine native int passt, wird es eine lange bleiben.

Nun, wenn Sie sich nicht um Genauigkeit kümmern, können Sie alle Ihre Mathe ops modulo maxint.

Ich weiß nicht, ob es schneller wäre, neugierig, aber man könnte numpy Arrays von einem Element anstelle von Ints verwenden.

Wenn die spezifische Berechnung, die Sie besorgt sind, ist ganzzahlige Exponentiation, dann gibt es einige Schlüsse, die wir zeichnen können:

 def smart_pow(mantissa, exponent, limit=int(math.ceil(math.log(sys.maxint)/math.log(2)))): if mantissa in (0, 1): return mantissa if exponent > limit: if mantissa == -1: return -1 if exponent&1 else 1 if mantissa > 1: return sys.maxint else: return (-1-sys.maxint) if exponent&1 else sys.maxint else: # this *might* overflow, but at least it won't take long return mantissa ** exponent 
  • Python-Code-Performance verringert sich mit Threading
  • Python vs Bash - In welcher Art von Aufgaben übertrifft jeder den anderen Performance-weise?
  • SqlAlchemy-Optimierungen für schreibgeschützte Objektmodelle
  • Beschleunige Iteration über Numpy Arrays / OpenCV cv2 Bild
  • Wie kommst du in Wörterbuch.keys () langsamer als Schlüssel im Wörterbuch?
  • Aktualisieren eines Python-Wörterbuchs beim Hinzufügen zu vorhandenen Schlüsseln?
  • Warum arbeitet mein Sieb von Eratosthenes schneller mit Ganzzahlen als mit Booleschen?
  • Hashlib in Windows und Linux
  • Wie beschleunige man Pandas multilevel dataframe sum?
  • Verbessere Pandas (PyTables?) HDF5 Tisch schreiben Leistung
  • Python Ausführung Geschwindigkeit: Laptop vs Desktop
  • Python ist die beste Programmiersprache der Welt.