decimal — Dezimal-Gleit- und Festkommaarithmetik¶
Quellcode: Lib/decimal.py
Das Modul decimal bietet Unterstützung für schnelle, korrekt gerundete Dezimal-Gleitkommaarithmetik. Es bietet mehrere Vorteile gegenüber dem Datentyp float
Dezimal „basiert auf einem Gleitkommamodell, das für Menschen konzipiert wurde, und hat zwangsläufig ein übergeordnetes Leitprinzip – Computer müssen eine Arithmetik bereitstellen, die auf die gleiche Weise funktioniert, wie Menschen sie in der Schule lernen.“ – Auszug aus der Spezifikation für Dezimalarithmetik.
Dezimalzahlen können exakt dargestellt werden. Im Gegensatz dazu haben Zahlen wie
1.1und2.2keine exakte Darstellung in binärer Gleitkommaarithmetik. Endbenutzer erwarten typischerweise nicht, dass1.1 + 2.2als3.3000000000000003angezeigt wird, wie es bei binärer Gleitkommaarithmetik der Fall ist.Die Exaktheit überträgt sich auf die Arithmetik. In der Dezimal-Gleitkommaarithmetik ist
0.1 + 0.1 + 0.1 - 0.3exakt gleich Null. In binärer Gleitkommaarithmetik ist das Ergebnis5.5511151231257827e-017. Obwohl nahe Null, verhindern die Unterschiede zuverlässige Gleichheitstests und Unterschiede können sich akkumulieren. Aus diesem Grund wird Dezimal in Buchhaltungsanwendungen bevorzugt, die strenge Gleichheitsinvarianten haben.Das Dezimalmodul beinhaltet eine Vorstellung von signifikanten Stellen, sodass
1.30 + 1.202.50ergibt. Die nachgestellte Null wird beibehalten, um die Signifikanz anzuzeigen. Dies ist die übliche Darstellung für Geldbeträge. Bei der Multiplikation verwendet der „Schulbuch“-Ansatz alle Ziffern der Faktoren. Zum Beispiel ergibt1.3 * 1.21.56, während1.30 * 1.201.5600ergibt.Im Gegensatz zur hardwarebasierten binären Gleitkommaarithmetik verfügt das Dezimalmodul über eine vom Benutzer veränderbare Genauigkeit (standardmäßig 28 Stellen), die für ein bestimmtes Problem beliebig groß sein kann
>>> from decimal import * >>> getcontext().prec = 6 >>> Decimal(1) / Decimal(7) Decimal('0.142857') >>> getcontext().prec = 28 >>> Decimal(1) / Decimal(7) Decimal('0.1428571428571428571428571429')
Sowohl binäre als auch dezimale Gleitkommaarithmetik werden auf der Grundlage veröffentlichter Standards implementiert. Während der eingebaute float-Typ nur einen geringen Teil seiner Fähigkeiten preisgibt, legt das Dezimalmodul alle erforderlichen Teile des Standards offen. Bei Bedarf hat der Programmierer die volle Kontrolle über Rundung und Signalbehandlung. Dies beinhaltet die Option, exakte Arithmetik zu erzwingen, indem Ausnahmen verwendet werden, um alle ungenauen Operationen zu blockieren.
Das Dezimalmodul wurde entwickelt, um „ohne Vorurteile sowohl exakte, ungerundete Dezimalarithmetik (manchmal als Festkommaarithmetik bezeichnet) als auch gerundete Gleitkommaarithmetik“ zu unterstützen. – Auszug aus der Spezifikation für Dezimalarithmetik.
Das Moduldesign konzentriert sich auf drei Konzepte: die Dezimalzahl, den Kontext für die Arithmetik und Signale.
Eine Dezimalzahl ist unveränderlich. Sie hat ein Vorzeichen, Koeffizientenziffern und einen Exponenten. Um die Signifikanz zu erhalten, werden die Koeffizientenziffern nicht auf nachgestellte Nullen gekürzt. Dezimalzahlen beinhalten auch Sonderwerte wie Infinity, -Infinity und NaN. Der Standard unterscheidet auch zwischen -0 und +0.
Der Kontext für die Arithmetik ist eine Umgebung, die Genauigkeit, Rundungsregeln, Exponentenlimits, Flags, die die Ergebnisse von Operationen anzeigen, und Trap-Schalter festlegt, die bestimmen, ob Signale als Ausnahmen behandelt werden. Zu den Rundungsoptionen gehören ROUND_CEILING, ROUND_DOWN, ROUND_FLOOR, ROUND_HALF_DOWN, ROUND_HALF_EVEN, ROUND_HALF_UP, ROUND_UP und ROUND_05UP.
Signale sind Gruppen von Ausnahmezuständen, die während der Berechnung auftreten. Abhängig von den Anforderungen der Anwendung können Signale ignoriert, als informativ betrachtet oder als Ausnahmen behandelt werden. Die Signale im Dezimalmodul sind: Clamped, InvalidOperation, DivisionByZero, Inexact, Rounded, Subnormal, Overflow, Underflow und FloatOperation.
Für jedes Signal gibt es ein Flag und einen Trap-Schalter. Wenn ein Signal angetroffen wird, wird sein Flag auf eins gesetzt, dann wird, wenn der Trap-Schalter auf eins gesetzt ist, eine Ausnahme ausgelöst. Flags sind klebend, daher muss der Benutzer sie zurücksetzen, bevor er eine Berechnung überwacht.
Siehe auch
IBM’s General Decimal Arithmetic Specification, The General Decimal Arithmetic Specification.
Schnellstart-Tutorial¶
Der übliche Start für die Verwendung von Dezimalzahlen ist der Import des Moduls, die Anzeige des aktuellen Kontexts mit getcontext() und, falls erforderlich, das Setzen neuer Werte für Genauigkeit, Rundung oder aktivierte Traps
>>> from decimal import *
>>> getcontext()
Context(prec=28, rounding=ROUND_HALF_EVEN, Emin=-999999, Emax=999999,
capitals=1, clamp=0, flags=[], traps=[Overflow, DivisionByZero,
InvalidOperation])
>>> getcontext().prec = 7 # Set a new precision
Dezimalinstanzen können aus ganzen Zahlen, Zeichenketten, Fließkommazahlen oder Tupeln konstruiert werden. Die Konstruktion aus einer ganzen Zahl oder einer Fließkommazahl führt zu einer exakten Umwandlung des Wertes dieser ganzen Zahl oder Fließkommazahl. Dezimalzahlen beinhalten Sonderwerte wie NaN, das für „Not a number“ steht, positive und negative Infinity und -0
>>> getcontext().prec = 28
>>> Decimal(10)
Decimal('10')
>>> Decimal('3.14')
Decimal('3.14')
>>> Decimal(3.14)
Decimal('3.140000000000000124344978758017532527446746826171875')
>>> Decimal((0, (3, 1, 4), -2))
Decimal('3.14')
>>> Decimal(str(2.0 ** 0.5))
Decimal('1.4142135623730951')
>>> Decimal(2) ** Decimal('0.5')
Decimal('1.414213562373095048801688724')
>>> Decimal('NaN')
Decimal('NaN')
>>> Decimal('-Infinity')
Decimal('-Infinity')
Wenn das Signal FloatOperation abgefangen wird, löst die versehentliche Mischung von Dezimalzahlen und Fließkommazahlen in Konstruktoren oder Vergleichsoperationen eine Ausnahme aus
>>> c = getcontext()
>>> c.traps[FloatOperation] = True
>>> Decimal(3.14)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
decimal.FloatOperation: [<class 'decimal.FloatOperation'>]
>>> Decimal('3.5') < 3.7
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
decimal.FloatOperation: [<class 'decimal.FloatOperation'>]
>>> Decimal('3.5') == 3.5
True
Hinzugefügt in Version 3.3.
Die Signifikanz einer neuen Dezimalzahl wird ausschließlich durch die Anzahl der eingegebenen Ziffern bestimmt. Kontextgenauigkeit und Rundung kommen nur bei arithmetischen Operationen zum Tragen.
>>> getcontext().prec = 6
>>> Decimal('3.0')
Decimal('3.0')
>>> Decimal('3.1415926535')
Decimal('3.1415926535')
>>> Decimal('3.1415926535') + Decimal('2.7182818285')
Decimal('5.85987')
>>> getcontext().rounding = ROUND_UP
>>> Decimal('3.1415926535') + Decimal('2.7182818285')
Decimal('5.85988')
Wenn die internen Grenzen der C-Version überschritten werden, löst die Konstruktion einer Dezimalzahl InvalidOperation aus
>>> Decimal("1e9999999999999999999")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
decimal.InvalidOperation: [<class 'decimal.InvalidOperation'>]
Geändert in Version 3.3.
Dezimalzahlen interagieren gut mit vielen anderen Teilen von Python. Hier ist ein kleines Flugmanöver mit dezimalen Gleitkommazahlen
>>> data = list(map(Decimal, '1.34 1.87 3.45 2.35 1.00 0.03 9.25'.split()))
>>> max(data)
Decimal('9.25')
>>> min(data)
Decimal('0.03')
>>> sorted(data)
[Decimal('0.03'), Decimal('1.00'), Decimal('1.34'), Decimal('1.87'),
Decimal('2.35'), Decimal('3.45'), Decimal('9.25')]
>>> sum(data)
Decimal('19.29')
>>> a,b,c = data[:3]
>>> str(a)
'1.34'
>>> float(a)
1.34
>>> round(a, 1)
Decimal('1.3')
>>> int(a)
1
>>> a * 5
Decimal('6.70')
>>> a * b
Decimal('2.5058')
>>> c % a
Decimal('0.77')
Und einige mathematische Funktionen sind auch für Dezimalzahlen verfügbar
>>> getcontext().prec = 28
>>> Decimal(2).sqrt()
Decimal('1.414213562373095048801688724')
>>> Decimal(1).exp()
Decimal('2.718281828459045235360287471')
>>> Decimal('10').ln()
Decimal('2.302585092994045684017991455')
>>> Decimal('10').log10()
Decimal('1')
Die Methode quantize() rundet eine Zahl auf einen festen Exponenten. Diese Methode ist nützlich für Geldbeträge, bei denen Ergebnisse oft auf eine feste Anzahl von Stellen gerundet werden
>>> Decimal('7.325').quantize(Decimal('.01'), rounding=ROUND_DOWN)
Decimal('7.32')
>>> Decimal('7.325').quantize(Decimal('1.'), rounding=ROUND_UP)
Decimal('8')
Wie oben gezeigt, greift die Funktion getcontext() auf den aktuellen Kontext zu und ermöglicht die Änderung der Einstellungen. Dieser Ansatz erfüllt die Bedürfnisse der meisten Anwendungen.
Für fortgeschrittenere Arbeiten kann es nützlich sein, alternative Kontexte mit dem Context()-Konstruktor zu erstellen. Um einen alternativen Kontext zu aktivieren, verwenden Sie die Funktion setcontext().
Im Einklang mit dem Standard bietet das Modul decimal zwei gebrauchsfertige Standardkontexte, BasicContext und ExtendedContext. Der erstere ist besonders nützlich für das Debugging, da viele der Traps aktiviert sind
>>> myothercontext = Context(prec=60, rounding=ROUND_HALF_DOWN)
>>> setcontext(myothercontext)
>>> Decimal(1) / Decimal(7)
Decimal('0.142857142857142857142857142857142857142857142857142857142857')
>>> ExtendedContext
Context(prec=9, rounding=ROUND_HALF_EVEN, Emin=-999999, Emax=999999,
capitals=1, clamp=0, flags=[], traps=[])
>>> setcontext(ExtendedContext)
>>> Decimal(1) / Decimal(7)
Decimal('0.142857143')
>>> Decimal(42) / Decimal(0)
Decimal('Infinity')
>>> setcontext(BasicContext)
>>> Decimal(42) / Decimal(0)
Traceback (most recent call last):
File "<pyshell#143>", line 1, in -toplevel-
Decimal(42) / Decimal(0)
DivisionByZero: x / 0
Kontexte haben auch Signal-Flags zur Überwachung von Ausnahmezuständen, die während Berechnungen auftreten. Die Flags bleiben gesetzt, bis sie explizit gelöscht werden. Daher ist es am besten, die Flags vor jedem Satz von überwachten Berechnungen mit der Methode clear_flags() zu löschen.
>>> setcontext(ExtendedContext)
>>> getcontext().clear_flags()
>>> Decimal(355) / Decimal(113)
Decimal('3.14159292')
>>> getcontext()
Context(prec=9, rounding=ROUND_HALF_EVEN, Emin=-999999, Emax=999999,
capitals=1, clamp=0, flags=[Inexact, Rounded], traps=[])
Der Eintrag _flags_ zeigt, dass die rationale Annäherung an pi gerundet wurde (Ziffern über die Kontextgenauigkeit hinaus wurden verworfen) und dass das Ergebnis ungenau ist (einige der verworfenen Ziffern waren ungleich Null).
Einzelne Traps werden mithilfe des Dictionaries im Attribut traps eines Kontexts gesetzt
>>> setcontext(ExtendedContext)
>>> Decimal(1) / Decimal(0)
Decimal('Infinity')
>>> getcontext().traps[DivisionByZero] = 1
>>> Decimal(1) / Decimal(0)
Traceback (most recent call last):
File "<pyshell#112>", line 1, in -toplevel-
Decimal(1) / Decimal(0)
DivisionByZero: x / 0
Die meisten Programme passen den aktuellen Kontext nur einmal am Anfang des Programms an. Und in vielen Anwendungen werden Daten mit einer einzigen Umwandlung innerhalb einer Schleife in Decimal konvertiert. Sobald der Kontext festgelegt und die Dezimalzahlen erstellt sind, wird der Großteil des Programms die Daten nicht anders als mit anderen numerischen Python-Typen behandeln.
Dezimalobjekte¶
- class decimal.Decimal(value='0', context=None)¶
Konstruiere ein neues
Decimal-Objekt basierend auf value.value kann eine ganze Zahl, eine Zeichenkette, ein Tupel, eine
floatoder ein anderesDecimal-Objekt sein. Wenn kein value angegeben ist, wirdDecimal('0')zurückgegeben. Wenn value eine Zeichenkette ist, muss sie der Syntax für Dezimalzahlen entsprechen, nachdem führende und nachgestellte Leerzeichen sowie durchgehende Unterstriche entfernt wurden.sign ::= '+' | '-' digit ::= '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' indicator ::= 'e' | 'E' digits ::= digit [digit]... decimal-part ::= digits '.' [digits] | ['.'] digits exponent-part ::= indicator [sign] digits infinity ::= 'Infinity' | 'Inf' nan ::= 'NaN' [digits] | 'sNaN' [digits] numeric-value ::= decimal-part [exponent-part] | infinity numeric-string ::= [sign] numeric-value | [sign] nan
Andere Unicode-Dezimalziffern sind ebenfalls zulässig, wo
digitoben erscheint. Dazu gehören Dezimalziffern aus verschiedenen anderen Alphabeten (z. B. Arabisch-Indische und Devanagari-Ziffern) sowie die Vollbreitenziffern'\uff10'bis'\uff19'. Die Groß-/Kleinschreibung ist nicht ausschlaggebend, daher sind beispielsweiseinf,Inf,INFINITYundiNfINityallesamt akzeptable Schreibweisen für positive Unendlichkeit.Wenn value ein
Tupelist, sollte es drei Komponenten haben: ein Vorzeichen (0für positiv oder1für negativ), einTupelvon Ziffern und einen ganzzahligen Exponenten. Zum Beispiel gibtDecimal((0, (1, 4, 1, 4), -3))Decimal('1.414')zurück.Wenn value eine
floatist, wird der binäre Gleitkommawert verlustfrei in seine exakte dezimale Entsprechung umgewandelt. Diese Umwandlung kann oft 53 oder mehr Ziffern Genauigkeit erfordern. Zum Beispiel konvertiertDecimal(float('1.1'))zuDecimal('1.100000000000000088817841970012523233890533447265625').Die Kontextgenauigkeit bestimmt nicht, wie viele Ziffern gespeichert werden. Diese wird ausschließlich durch die Anzahl der Ziffern in value bestimmt. Zum Beispiel zeichnet
Decimal('3.00000')alle fünf Nullen auf, auch wenn die Kontextgenauigkeit nur drei beträgt.Der Zweck des context-Arguments besteht darin zu bestimmen, was zu tun ist, wenn value eine fehlerhafte Zeichenkette ist. Wenn der Kontext
InvalidOperationabfängt, wird eine Ausnahme ausgelöst; andernfalls gibt der Konstruktor eine neue Dezimalzahl mit dem WertNaNzurück.Nach der Konstruktion sind
Decimal-Objekte unveränderlich.Geändert in Version 3.2: Das Argument für den Konstruktor darf nun auch eine
float-Instanz sein.Geändert in Version 3.3:
float-Argumente lösen eine Ausnahme aus, wenn der TrapFloatOperationgesetzt ist. Standardmäßig ist der Trap deaktiviert.Geändert in Version 3.6: Unterstriche sind zur Gruppierung zulässig, wie bei Ganzzahl- und Gleitkommaliteralen im Code.
Dezimale Gleitkommaobjekte teilen viele Eigenschaften mit den anderen eingebauten numerischen Typen wie
floatundint. Alle üblichen mathematischen Operationen und Sonderfunktionen gelten. Ebenso können Dezimalobjekte kopiert, gepickelt, gedruckt, als Wörterbuchschlüssel, als Set-Elemente verwendet, verglichen, sortiert und in einen anderen Typ (wiefloatoderint) umgewandelt werden.Es gibt einige kleine Unterschiede zwischen der Arithmetik von Dezimalobjekten und der Arithmetik von ganzen Zahlen und Fließkommazahlen. Wenn der Restoperator
%auf Dezimalobjekte angewendet wird, ist das Vorzeichen des Ergebnisses das Vorzeichen des *Dividenden* und nicht das des Divisors.>>> (-7) % 4 1 >>> Decimal(-7) % Decimal(4) Decimal('-3')
Der Ganzzahl-Divisionsoperator
//verhält sich analog und gibt den ganzzahligen Teil des wahren Quotienten zurück (Abschneiden in Richtung Null) anstatt seines Bodens, um die übliche Identitätx == (x // y) * y + x % yzu erhalten.>>> -7 // 4 -2 >>> Decimal(-7) // Decimal(4) Decimal('-1')
Die Operatoren
%und//implementieren die Operationenremainderunddivide-integer(jeweils) gemäß der Spezifikation.Dezimalobjekte können im Allgemeinen nicht mit Fließkommazahlen oder Instanzen von
fractions.Fractionin arithmetischen Operationen kombiniert werden: Der Versuch, eineDecimalzu einerfloathinzuzufügen, löst beispielsweise einenTypeErroraus. Es ist jedoch möglich, Pythons Vergleichsoperatoren zu verwenden, um eineDecimal-Instanzxmit einer anderen Zahlyzu vergleichen. Dies vermeidet verwirrende Ergebnisse beim Gleichheitsvergleich zwischen Zahlen unterschiedlicher Typen.Geändert in Version 3.2: Gemischte Vergleiche zwischen
Decimal-Instanzen und anderen numerischen Typen werden nun vollständig unterstützt.Neben den standardmäßigen numerischen Eigenschaften verfügen dezimale Gleitkommaobjekte auch über eine Reihe spezialisierter Methoden
- adjusted()¶
Gibt den angepassten Exponenten zurück, nachdem die rechtesten Ziffern des Koeffizienten verschoben wurden, bis nur noch die führende Ziffer übrig bleibt:
Decimal('321e+5').adjusted()gibt sieben zurück. Wird zur Bestimmung der Position der signifikantesten Ziffer in Bezug auf den Dezimalpunkt verwendet.
- as_integer_ratio()¶
Gibt ein Paar
(n, d)von ganzen Zahlen zurück, das die gegebeneDecimal-Instanz als Bruch darstellt, gekürzt und mit positivem Nenner.>>> Decimal('-3.14').as_integer_ratio() (-157, 50)
Die Umwandlung ist exakt. Löst OverflowError bei Unendlichkeiten und ValueError bei NaNs aus.
Hinzugefügt in Version 3.6.
- as_tuple()¶
Gibt eine benannte Tupel-Darstellung der Zahl zurück:
DecimalTuple(sign, digits, exponent).
- canonical()¶
Gibt die kanonische Kodierung des Arguments zurück. Derzeit ist die Kodierung einer
Decimal-Instanz immer kanonisch, daher gibt diese Operation ihr Argument unverändert zurück.
- compare(other, context=None)¶
Vergleiche die Werte zweier Dezimalinstanzen.
compare()gibt eine Dezimalinstanz zurück, und wenn einer der Operanden ein NaN ist, ist das Ergebnis ein NaN.a or b is a NaN ==> Decimal('NaN') a < b ==> Decimal('-1') a == b ==> Decimal('0') a > b ==> Decimal('1')
- compare_signal(other, context=None)¶
Diese Operation ist identisch mit der Methode
compare(), mit der Ausnahme, dass alle NaNs ein Signal senden. Das heißt, wenn keiner der Operanden ein Signal-NaN ist, wird ein stilles NaN-Operand so behandelt, als wäre er ein Signal-NaN.
- compare_total(other, context=None)¶
Vergleiche zwei Operanden anhand ihrer abstrakten Darstellung anstatt ihres numerischen Werts. Ähnlich wie bei der Methode
compare(), aber das Ergebnis liefert eine totale Ordnung fürDecimal-Instanzen. ZweiDecimal-Instanzen mit demselben numerischen Wert, aber unterschiedlichen Darstellungen vergleichen sich in dieser Ordnung ungleich.>>> Decimal('12.0').compare_total(Decimal('12')) Decimal('-1')
Stille und Signal-NaNs sind ebenfalls in der totalen Ordnung enthalten. Das Ergebnis dieser Funktion ist
Decimal('0'), wenn beide Operanden die gleiche Darstellung haben,Decimal('-1'), wenn der erste Operand in der totalen Ordnung niedriger ist als der zweite, undDecimal('1'), wenn der erste Operand in der totalen Ordnung höher ist als der zweite Operand. Details zur totalen Ordnung finden Sie in der Spezifikation.Diese Operation wird vom Kontext nicht beeinflusst und ist still: Es werden keine Flags geändert und keine Rundung durchgeführt. Als Ausnahme kann die C-Version InvalidOperation auslösen, wenn der zweite Operand nicht exakt umgewandelt werden kann.
- compare_total_mag(other, context=None)¶
Vergleiche zwei Operanden anhand ihrer abstrakten Darstellung anstatt ihres Werts wie in
compare_total(), ignoriere aber das Vorzeichen jedes Operanden.x.compare_total_mag(y)ist äquivalent zux.copy_abs().compare_total(y.copy_abs()).Diese Operation wird vom Kontext nicht beeinflusst und ist still: Es werden keine Flags geändert und keine Rundung durchgeführt. Als Ausnahme kann die C-Version InvalidOperation auslösen, wenn der zweite Operand nicht exakt umgewandelt werden kann.
- conjugate()¶
Gibt einfach self zurück; diese Methode dient nur der Einhaltung der Dezimalspezifikation.
- copy_abs()¶
Gibt den Absolutwert des Arguments zurück. Diese Operation wird vom Kontext nicht beeinflusst und ist still: Es werden keine Flags geändert und keine Rundung durchgeführt.
- copy_negate()¶
Gibt die Negation des Arguments zurück. Diese Operation wird vom Kontext nicht beeinflusst und ist still: Es werden keine Flags geändert und keine Rundung durchgeführt.
- copy_sign(other, context=None)¶
Gibt eine Kopie des ersten Operanden zurück, deren Vorzeichen mit dem Vorzeichen des zweiten Operanden übereinstimmt. Zum Beispiel
>>> Decimal('2.3').copy_sign(Decimal('-1.5')) Decimal('-2.3')
Diese Operation wird vom Kontext nicht beeinflusst und ist still: Es werden keine Flags geändert und keine Rundung durchgeführt. Als Ausnahme kann die C-Version InvalidOperation auslösen, wenn der zweite Operand nicht exakt umgewandelt werden kann.
- exp(context=None)¶
Gibt den Wert der (natürlichen) Exponentialfunktion
e**xfür die gegebene Zahl zurück. Das Ergebnis wird mit demROUND_HALF_EVENRundungsmodus korrekt gerundet.>>> Decimal(1).exp() Decimal('2.718281828459045235360287471') >>> Decimal(321).exp() Decimal('2.561702493119680037517373933E+139')
- classmethod from_float(f, /)¶
Alternativer Konstruktor, der nur Instanzen von
floatoderintakzeptiert.Hinweis:
Decimal.from_float(0.1)ist nicht dasselbe wieDecimal('0.1'). Da 0.1 in binärer Gleitkommadarstellung nicht exakt darstellbar ist, wird der Wert als nächstgelegener darstellbarer Wert gespeichert, der0x1.999999999999ap-4ist. Dieser äquivalente Wert in Dezimal ist0.1000000000000000055511151231257827021181583404541015625.>>> Decimal.from_float(0.1) Decimal('0.1000000000000000055511151231257827021181583404541015625') >>> Decimal.from_float(float('nan')) Decimal('NaN') >>> Decimal.from_float(float('inf')) Decimal('Infinity') >>> Decimal.from_float(float('-inf')) Decimal('-Infinity')
Hinzugefügt in Version 3.1.
- classmethod from_number(number, /)¶
Alternativer Konstruktor, der nur Instanzen von
float,intoderDecimalakzeptiert, aber keine Strings oder Tupel.>>> Decimal.from_number(314) Decimal('314') >>> Decimal.from_number(0.1) Decimal('0.1000000000000000055511151231257827021181583404541015625') >>> Decimal.from_number(Decimal('3.14')) Decimal('3.14')
Hinzugefügt in Version 3.14.
- fma(other, third, context=None)¶
Fused Multiply-Add. Gibt self*other+third ohne Rundung des Zwischenprodukts self*other zurück.
>>> Decimal(2).fma(3, 5) Decimal('11')
- is_canonical()¶
Gibt
Truezurück, wenn das Argument kanonisch ist, undFalseandernfalls. Derzeit ist eineDecimal-Instanz immer kanonisch, daher gibt diese Operation immerTruezurück.
- is_finite()¶
Gibt
Truezurück, wenn das Argument eine endliche Zahl ist, undFalse, wenn das Argument eine Unendlichkeit oder NaN ist.
- is_infinite()¶
Gibt
Truezurück, wenn das Argument entweder positiv oder negativ unendlich ist, undFalseandernfalls.
- is_nan()¶
Gibt
Truezurück, wenn das Argument ein (quiet oder signaling) NaN ist, undFalseandernfalls.
- is_normal(context=None)¶
Gibt
Truezurück, wenn das Argument eine normale endliche Zahl ist. GibtFalsezurück, wenn das Argument Null, subnormal, unendlich oder ein NaN ist.
- is_signed()¶
Gibt
Truezurück, wenn das Argument ein negatives Vorzeichen hat, undFalseandernfalls. Beachten Sie, dass Nullen und NaNs beide Vorzeichen tragen können.
- is_subnormal(context=None)¶
Gibt
Truezurück, wenn das Argument subnormal ist, undFalseandernfalls.
- is_zero()¶
Gibt
Truezurück, wenn das Argument ein (positives oder negatives) Null ist, undFalseandernfalls.
- ln(context=None)¶
Gibt den natürlichen (Basis e) Logarithmus des Operanden zurück. Das Ergebnis wird mit dem
ROUND_HALF_EVENRundungsmodus korrekt gerundet.
- log10(context=None)¶
Gibt den Logarithmus zur Basis zehn des Operanden zurück. Das Ergebnis wird mit dem
ROUND_HALF_EVENRundungsmodus korrekt gerundet.
- logb(context=None)¶
Für eine von Null verschiedene Zahl gibt den angepassten Exponenten ihres Operanden als
Decimal-Instanz zurück. Wenn der Operand Null ist, wirdDecimal('-Infinity')zurückgegeben und das FlagDivisionByZerogesetzt. Wenn der Operand unendlich ist, wirdDecimal('Infinity')zurückgegeben.
- logical_and(other, context=None)¶
logical_and()ist eine logische Operation, die zwei logische Operanden (siehe Logische Operanden) entgegennimmt. Das Ergebnis ist das ziffernweiseandder beiden Operanden.
- logical_invert(context=None)¶
logical_invert()ist eine logische Operation. Das Ergebnis ist die ziffernweise Invertierung des Operanden.
- logical_or(other, context=None)¶
logical_or()ist eine logische Operation, die zwei logische Operanden (siehe Logische Operanden) entgegennimmt. Das Ergebnis ist das ziffernweiseorder beiden Operanden.
- logical_xor(other, context=None)¶
logical_xor()ist eine logische Operation, die zwei logische Operanden (siehe Logische Operanden) entgegennimmt. Das Ergebnis ist das ziffernweise exklusive Oder der beiden Operanden.
- max(other, context=None)¶
Wie
max(self, other), außer dass die Rundungsregel des Kontexts vor der Rückgabe angewendet wird undNaN-Werte entweder signalisiert oder ignoriert werden (abhängig vom Kontext und davon, ob sie signaling oder quiet sind).
- max_mag(other, context=None)¶
Ähnlich wie die Methode
max(), aber der Vergleich wird mit den absoluten Werten der Operanden durchgeführt.
- min(other, context=None)¶
Wie
min(self, other), außer dass die Rundungsregel des Kontexts vor der Rückgabe angewendet wird undNaN-Werte entweder signalisiert oder ignoriert werden (abhängig vom Kontext und davon, ob sie signaling oder quiet sind).
- min_mag(other, context=None)¶
Ähnlich wie die Methode
min(), aber der Vergleich wird mit den absoluten Werten der Operanden durchgeführt.
- next_minus(context=None)¶
Gibt die größte im gegebenen Kontext (oder im Kontext des aktuellen Threads, wenn kein Kontext angegeben ist) darstellbare Zahl zurück, die kleiner als der gegebene Operand ist.
- next_plus(context=None)¶
Gibt die kleinste im gegebenen Kontext (oder im Kontext des aktuellen Threads, wenn kein Kontext angegeben ist) darstellbare Zahl zurück, die größer als der gegebene Operand ist.
- next_toward(other, context=None)¶
Wenn die beiden Operanden ungleich sind, wird die Zahl zurückgegeben, die dem ersten Operanden in Richtung des zweiten Operanden am nächsten liegt. Wenn beide Operanden numerisch gleich sind, wird eine Kopie des ersten Operanden mit dem Vorzeichen des zweiten Operanden zurückgegeben.
- normalize(context=None)¶
Wird verwendet, um kanonische Werte einer Äquivalenzklasse innerhalb des aktuellen Kontexts oder des angegebenen Kontexts zu erzeugen.
Dies hat die gleiche Semantik wie die unäre Plus-Operation, mit der Ausnahme, dass, wenn das Endergebnis endlich ist, es auf seine einfachste Form reduziert wird, wobei alle nachgestellten Nullen entfernt und sein Vorzeichen beibehalten werden. Das heißt, solange der Koeffizient nicht Null und ein Vielfaches von zehn ist, wird der Koeffizient durch zehn geteilt und der Exponent um 1 erhöht. Andernfalls (der Koeffizient ist Null) wird der Exponent auf 0 gesetzt. In allen Fällen bleibt das Vorzeichen unverändert.
Zum Beispiel werden
Decimal('32.100')undDecimal('0.321000e+2')beide zu dem äquivalenten WertDecimal('32.1')normalisiert.Beachten Sie, dass die Rundung vor der Reduzierung auf die einfachste Form angewendet wird.
In den neuesten Versionen der Spezifikation ist diese Operation auch als
reducebekannt.
- number_class(context=None)¶
Gibt einen String zurück, der die Klasse des Operanden beschreibt. Der zurückgegebene Wert ist einer der folgenden zehn Strings.
"-Infinity", was bedeutet, dass der Operand negative Unendlichkeit ist."-Normal", was bedeutet, dass der Operand eine negative normale Zahl ist."-Subnormal", was bedeutet, dass der Operand negativ und subnormal ist."-Zero", was bedeutet, dass der Operand eine negative Null ist."+Zero", was bedeutet, dass der Operand eine positive Null ist."+Subnormal", was bedeutet, dass der Operand positiv und subnormal ist."+Normal", was bedeutet, dass der Operand eine positive normale Zahl ist."+Infinity", was bedeutet, dass der Operand positive Unendlichkeit ist."NaN", was bedeutet, dass der Operand ein Quiet NaN (Not a Number) ist."sNaN", was bedeutet, dass der Operand ein Signaling NaN ist.
- quantize(exp, rounding=None, context=None)¶
Gibt einen Wert zurück, der dem ersten Operanden nach Rundung und mit dem Exponenten des zweiten Operanden entspricht.
>>> Decimal('1.41421356').quantize(Decimal('1.000')) Decimal('1.414')
Im Gegensatz zu anderen Operationen wird, wenn die Länge des Koeffizienten nach der Quantisierungsoperation größer als die Präzision wäre, eine
InvalidOperationsignalisiert. Dies garantiert, dass, sofern keine Fehlerbedingung vorliegt, der quantisierte Exponent immer gleich dem des rechten Operanden ist.Im Gegensatz zu anderen Operationen signalisiert quantize niemals Unterlauf (Underflow), selbst wenn das Ergebnis subnormal und ungenau ist.
Wenn der Exponent des zweiten Operanden größer ist als der des ersten, kann eine Rundung erforderlich sein. In diesem Fall wird der Rundungsmodus durch das Argument
roundingbestimmt, falls angegeben, andernfalls durch das gegebene Argumentcontext; wenn keines der Argumente angegeben ist, wird der Rundungsmodus des Kontexts des aktuellen Threads verwendet.Ein Fehler wird zurückgegeben, wenn der resultierende Exponent größer als
Emaxoder kleiner alsEtiny()ist.
- radix()¶
Gibt
Decimal(10)zurück, die Radix (Basis), in der dieDecimal-Klasse alle ihre Berechnungen durchführt. Zur Kompatibilität mit der Spezifikation enthalten.
- remainder_near(other, context=None)¶
Gibt den Rest der Division von self durch other zurück. Dies unterscheidet sich von
self % otherdadurch, dass das Vorzeichen des Rests so gewählt wird, dass sein absoluter Wert minimiert wird. Genauer gesagt ist der Rückgabewertself - n * other, wobeindie nächste ganze Zahl zum exakten Wert vonself / otherist, und wenn zwei ganze Zahlen gleich nahe sind, wird die gerade Zahl gewählt.Wenn das Ergebnis Null ist, hat es das Vorzeichen von self.
>>> Decimal(18).remainder_near(Decimal(10)) Decimal('-2') >>> Decimal(25).remainder_near(Decimal(10)) Decimal('5') >>> Decimal(35).remainder_near(Decimal(10)) Decimal('-5')
- rotate(other, context=None)¶
Gibt das Ergebnis der Rotation der Ziffern des ersten Operanden um einen durch den zweiten Operanden angegebenen Betrag zurück. Der zweite Operand muss eine ganze Zahl im Bereich von -precision bis precision sein. Der absolute Wert des zweiten Operanden gibt die Anzahl der Stellen an, um die rotiert wird. Wenn der zweite Operand positiv ist, erfolgt die Rotation nach links; andernfalls erfolgt die Rotation nach rechts. Ziffern, die in den Koeffizienten rotiert werden, sind Nullen. Das Vorzeichen und der Exponent des ersten Operanden bleiben unverändert.
- same_quantum(other, context=None)¶
Prüft, ob self und other den gleichen Exponenten haben oder ob beide
NaNsind.Diese Operation wird vom Kontext nicht beeinflusst und ist still: Es werden keine Flags geändert und keine Rundung durchgeführt. Als Ausnahme kann die C-Version InvalidOperation auslösen, wenn der zweite Operand nicht exakt umgewandelt werden kann.
- scaleb(other, context=None)¶
Gibt den ersten Operanden mit angepasstem Exponenten durch den zweiten zurück. Äquivalent dazu: gibt den ersten Operanden multipliziert mit
10**otherzurück. Der zweite Operand muss eine ganze Zahl sein.
- shift(other, context=None)¶
Gibt das Ergebnis der Verschiebung der Ziffern des ersten Operanden um einen durch den zweiten Operanden angegebenen Betrag zurück. Der zweite Operand muss eine ganze Zahl im Bereich von -precision bis precision sein. Der absolute Wert des zweiten Operanden gibt die Anzahl der Stellen an, um die verschoben wird. Wenn der zweite Operand positiv ist, erfolgt die Verschiebung nach links; andernfalls erfolgt die Verschiebung nach rechts. In den Koeffizienten hineingeschobene Ziffern sind Nullen. Das Vorzeichen und der Exponent des ersten Operanden bleiben unverändert.
- sqrt(context=None)¶
Gibt die Quadratwurzel des Arguments mit voller Präzision zurück.
- to_eng_string(context=None)¶
Konvertiert in einen String, der eine Ingenieursschreibweise verwendet, wenn ein Exponent benötigt wird.
Die Ingenieursschreibweise hat einen Exponenten, der ein Vielfaches von 3 ist. Dies kann bis zu 3 Ziffern links vom Dezimalpunkt belassen und erfordert möglicherweise das Hinzufügen von ein oder zwei nachgestellten Nullen.
Zum Beispiel konvertiert dies
Decimal('123E+1')zuDecimal('1.23E+3').
- to_integral(rounding=None, context=None)¶
Identisch mit der Methode
to_integral_value(). Der Nameto_integralwurde zur Kompatibilität mit älteren Versionen beibehalten.
- to_integral_exact(rounding=None, context=None)¶
Auf die nächste Ganzzahl runden, wobei bei Rundung entsprechend
InexactoderRoundedsignalisiert wird. Der Rundungsmodus wird durch den Parameterroundingbestimmt, falls angegeben, andernfalls durch den angegebenencontext. Wenn keiner der Parameter angegeben ist, wird der Rundungsmodus des aktuellen Kontexts verwendet.
- to_integral_value(rounding=None, context=None)¶
Auf die nächste Ganzzahl runden, ohne
InexactoderRoundedzu signalisieren. Falls angegeben, wird das rounding angewendet; andernfalls wird die Rundungsmethode des bereitgestellten context oder des aktuellen Kontexts verwendet.
Dezimalzahlen können mit der Funktion
round()gerundet werden.- round(number)
- round(number, ndigits)
Wenn ndigits nicht angegeben oder
Noneist, wird die nächsteintzu number zurückgegeben, wobei bei Gleichstand zur nächsten geraden Zahl gerundet wird und der Rundungsmodus desDecimal-Kontexts ignoriert wird. LöstOverflowErroraus, wenn number eine Unendlichkeit ist, oderValueError, wenn es sich um eine (ruhige oder signalisierende) NaN handelt.Wenn ndigits ein
intist, wird der Rundungsmodus des Kontexts beachtet und einDecimal, das number auf das nächste Vielfache vonDecimal('1E-ndigits')gerundet darstellt, zurückgegeben; in diesem Fall istround(number, ndigits)äquivalent zuself.quantize(Decimal('1E-ndigits')). GibtDecimal('NaN')zurück, wenn number eine ruhige NaN ist. LöstInvalidOperationaus, wenn number eine Unendlichkeit, eine signalisierende NaN ist oder wenn die Länge des Koeffizienten nach der Quantisierungsoperation größer als die aktuelle Präzision des Kontexts wäre. Anders ausgedrückt, für die Nicht-Eckfällewenn ndigits positiv ist, geben Sie number auf ndigits Dezimalstellen gerundet zurück;
wenn ndigits null ist, geben Sie number auf die nächste Ganzzahl gerundet zurück;
wenn ndigits negativ ist, geben Sie number auf das nächste Vielfache von
10**abs(ndigits)gerundet zurück.
Zum Beispiel
>>> from decimal import Decimal, getcontext, ROUND_DOWN >>> getcontext().rounding = ROUND_DOWN >>> round(Decimal('3.75')) # context rounding ignored 4 >>> round(Decimal('3.5')) # round-ties-to-even 4 >>> round(Decimal('3.75'), 0) # uses the context rounding Decimal('3') >>> round(Decimal('3.75'), 1) Decimal('3.7') >>> round(Decimal('3.75'), -1) Decimal('0E+1')
Logische Operanden¶
Die Methoden logical_and(), logical_invert(), logical_or() und logical_xor() erwarten, dass ihre Argumente logische Operanden sind. Ein logischer Operand ist eine Decimal-Instanz, deren Exponent und Vorzeichen beide null sind und deren Ziffern alle entweder 0 oder 1 sind.
Kontext-Objekte¶
Kontexte sind Umgebungen für arithmetische Operationen. Sie steuern die Genauigkeit, legen Regeln für die Rundung fest, bestimmen, welche Signale als Ausnahmen behandelt werden, und begrenzen den Bereich für Exponenten.
Jeder Thread hat seinen eigenen aktuellen Kontext, auf den über die Funktionen getcontext() und setcontext() zugegriffen oder der geändert werden kann.
- decimal.getcontext()¶
Gibt den aktuellen Kontext für den aktiven Thread zurück.
- decimal.setcontext(c, /)¶
Setzt den aktuellen Kontext für den aktiven Thread auf c.
Sie können auch die with-Anweisung und die Funktion localcontext() verwenden, um den aktiven Kontext vorübergehend zu ändern.
- decimal.localcontext(ctx=None, **kwargs)¶
Gibt einen Kontextmanager zurück, der den aktuellen Kontext für den aktiven Thread beim Eintritt in die with-Anweisung auf eine Kopie von ctx setzt und den vorherigen Kontext beim Verlassen der with-Anweisung wiederherstellt. Wenn kein Kontext angegeben wird, wird eine Kopie des aktuellen Kontexts verwendet. Das Argument kwargs wird verwendet, um die Attribute des neuen Kontexts festzulegen.
Zum Beispiel setzt der folgende Code die aktuelle Dezimalgenauigkeit auf 42 Stellen, führt eine Berechnung durch und stellt dann automatisch den vorherigen Kontext wieder her.
from decimal import localcontext with localcontext() as ctx: ctx.prec = 42 # Perform a high precision calculation s = calculate_something() s = +s # Round the final result back to the default precision
Unter Verwendung von Schlüsselwortargumenten wäre der Code wie folgt:
from decimal import localcontext with localcontext(prec=42) as ctx: s = calculate_something() s = +s
Löst
TypeErroraus, wenn kwargs ein Attribut liefert, dasContextnicht unterstützt. Löst entwederTypeErroroderValueErroraus, wenn kwargs einen ungültigen Wert für ein Attribut liefert.Geändert in Version 3.11:
localcontext()unterstützt jetzt das Setzen von Kontextattributen durch die Verwendung von Schlüsselwortargumenten.
- decimal.IEEEContext(bits)¶
Gibt ein Kontextobjekt zurück, das für eines der IEEE-Austauschformate initialisiert ist. Das Argument muss ein Vielfaches von 32 sein und kleiner als
IEEE_CONTEXT_MAX_BITS.Hinzugefügt in Version 3.14.
Neue Kontexte können auch mit dem unten beschriebenen Konstruktor Context erstellt werden. Zusätzlich bietet das Modul drei vordefinierte Kontexte
- decimal.BasicContext¶
Dies ist ein Standardkontext, der durch die General Decimal Arithmetic Specification definiert ist. Die Genauigkeit ist auf neun eingestellt. Die Rundung ist auf
ROUND_HALF_UPeingestellt. Alle Flags sind gelöscht. Alle Traps sind aktiviert (werden als Ausnahmen behandelt) außerInexact,RoundedundSubnormal.Da viele der Traps aktiviert sind, ist dieser Kontext für das Debugging nützlich.
- decimal.ExtendedContext¶
Dies ist ein Standardkontext, der durch die General Decimal Arithmetic Specification definiert ist. Die Genauigkeit ist auf neun eingestellt. Die Rundung ist auf
ROUND_HALF_EVENeingestellt. Alle Flags sind gelöscht. Keine Traps sind aktiviert (so dass während der Berechnungen keine Ausnahmen ausgelöst werden).Da die Traps deaktiviert sind, ist dieser Kontext für Anwendungen nützlich, die statt Ausnahmen den Ergebniswert
NaNoderInfinitybevorzugen. Dies ermöglicht es einer Anwendung, einen Lauf in Anwesenheit von Bedingungen abzuschließen, die das Programm sonst stoppen würden.
- decimal.DefaultContext¶
Dieser Kontext wird vom Konstruktor
Contextals Prototyp für neue Kontexte verwendet. Das Ändern eines Feldes (wie z. B. der Genauigkeit) hat zur Folge, dass der Standardwert für neue Kontexte, die vom KonstruktorContexterstellt werden, geändert wird.Dieser Kontext ist am nützlichsten in Multithreading-Umgebungen. Das Ändern eines der Felder, bevor Threads gestartet werden, hat zur Folge, dass systemweite Standardwerte gesetzt werden. Das Ändern der Felder, nachdem Threads gestartet wurden, wird nicht empfohlen, da dies eine Threadsynchronisation erfordert, um Race Conditions zu vermeiden.
In Single-Thread-Umgebungen ist es vorzuziehen, diesen Kontext überhaupt nicht zu verwenden. Erstellen Sie stattdessen einfach explizit Kontexte, wie unten beschrieben.
Die Standardwerte sind
Context.prec=28,Context.rounding=ROUND_HALF_EVENund aktivierte Traps fürOverflow,InvalidOperationundDivisionByZero.
Zusätzlich zu den drei bereitgestellten Kontexten können neue Kontexte mit dem Konstruktor Context erstellt werden.
- class decimal.Context(prec=None, rounding=None, Emin=None, Emax=None, capitals=None, clamp=None, flags=None, traps=None)¶
Erstellt einen neuen Kontext. Wenn ein Feld nicht angegeben oder
Noneist, werden die Standardwerte ausDefaultContextkopiert. Wenn das Feld flags nicht angegeben oderNoneist, werden alle Flags gelöscht.- prec¶
Eine Ganzzahl im Bereich [
1,MAX_PREC], die die Genauigkeit für arithmetische Operationen im Kontext festlegt.
- rounding¶
Eine der Konstanten, die im Abschnitt Rounding Modes aufgeführt sind.
- traps¶
- flags¶
Listen von beliebigen Signalen, die gesetzt werden sollen. Im Allgemeinen sollten neue Kontexte nur Traps setzen und die Flags gelöscht lassen.
- Emin¶
- Emax¶
Ganzzahlen, die die zulässigen äußeren Grenzen für Exponenten angeben. Emin muss im Bereich [
MIN_EMIN,0] liegen, Emax im Bereich [0,MAX_EMAX].
- capitals¶
Entweder
0oder1(Standard). Wenn auf1gesetzt, werden Exponenten mit einem GroßbuchstabenEausgegeben; andernfalls wird ein Kleinbuchstabeeverwendet:Decimal('6.02e+23').
- clamp¶
Entweder
0(Standard) oder1. Wenn auf1gesetzt, ist der Exponenteeiner in diesem Kontext darstellbarenDecimal-Instanz streng auf den BereichEmin - prec + 1 <= e <= Emax - prec + 1beschränkt. Wenn clamp0ist, gilt eine schwächere Bedingung: Der angepasste Exponent derDecimal-Instanz ist höchstensEmax. Wenn clamp1ist, wird eine große normale Zahl, wo möglich, ihren Exponenten reduziert und eine entsprechende Anzahl von Nullen zu ihrem Koeffizienten hinzugefügt, um die Exponentenbeschränkungen zu erfüllen; dies bewahrt den Wert der Zahl, geht aber Informationen über signifikante nachfolgende Nullen verloren. Zum Beispiel>>> Context(prec=6, Emax=999, clamp=1).create_decimal('1.23e999') Decimal('1.23000E+999')
Ein clamp-Wert von
1ermöglicht Kompatibilität mit den Festbreiten-Dezimal-Austauschformaten, die in IEEE 754 spezifiziert sind.
Die Klasse
Contextdefiniert mehrere Allzweckmethoden sowie eine große Anzahl von Methoden zur direkten Durchführung von Berechnungen in einem gegebenen Kontext. Zusätzlich gibt es für jede der oben beschriebenen Methoden fürDecimal(mit Ausnahme der Methodenadjusted()undas_tuple()) eine entsprechendeContext-Methode. Zum Beispiel ist für eineContext-InstanzCund eineDecimal-Instanzx,C.exp(x)äquivalent zux.exp(context=C). JedeContext-Methode akzeptiert eine Python-Ganzzahl (eine Instanz vonint) überall dort, wo eine Decimal-Instanz akzeptiert wird.- clear_flags()¶
Setzt alle Flags auf
0zurück.
- clear_traps()¶
Setzt alle Traps auf
0zurück.Hinzugefügt in Version 3.3.
- copy()¶
Gibt eine Duplikat des Kontexts zurück.
- copy_decimal(num, /)¶
Gibt eine Kopie der Decimal-Instanz num zurück.
- create_decimal(num='0', /)¶
Erstellt eine neue Decimal-Instanz aus num, verwendet aber self als Kontext. Im Gegensatz zum Konstruktor
Decimalwerden die Kontextgenauigkeit, die Rundungsmethode, die Flags und die Traps auf die Konvertierung angewendet.Dies ist nützlich, da Konstanten oft mit höherer Genauigkeit als für die Anwendung erforderlich angegeben werden. Ein weiterer Vorteil ist, dass die Rundung sofort unerwünschte Auswirkungen von Ziffern über die aktuelle Genauigkeit hinaus beseitigt. Im folgenden Beispiel bedeutet die Verwendung von ungerundeten Eingaben, dass das Hinzufügen von Null zu einer Summe das Ergebnis ändern kann.
>>> getcontext().prec = 3 >>> Decimal('3.4445') + Decimal('1.0023') Decimal('4.45') >>> Decimal('3.4445') + Decimal(0) + Decimal('1.0023') Decimal('4.44')
Diese Methode implementiert die To-Number-Operation der IBM-Spezifikation. Wenn das Argument eine Zeichenkette ist, sind keine führenden oder nachfolgenden Leerzeichen oder Unterstriche erlaubt.
- create_decimal_from_float(f, /)¶
Erstellt eine neue Decimal-Instanz aus einem Float f, rundet aber unter Verwendung von self als Kontext. Im Gegensatz zur Klassenmethode
Decimal.from_float()werden die Kontextgenauigkeit, die Rundungsmethode, die Flags und die Traps auf die Konvertierung angewendet.>>> context = Context(prec=5, rounding=ROUND_DOWN) >>> context.create_decimal_from_float(math.pi) Decimal('3.1415') >>> context = Context(prec=5, traps=[Inexact]) >>> context.create_decimal_from_float(math.pi) Traceback (most recent call last): ... decimal.Inexact: None
Hinzugefügt in Version 3.1.
- Etiny()¶
Gibt einen Wert zurück, der gleich
Emin - prec + 1ist, was der minimale Exponentenwert für subnormale Ergebnisse ist. Wenn ein Unterlauf auftritt, wird der Exponent aufEtinygesetzt.
- Etop()¶
Gibt einen Wert zurück, der gleich
Emax - prec + 1ist.
Der übliche Ansatz für die Arbeit mit Dezimalzahlen besteht darin,
Decimal-Instanzen zu erstellen und dann arithmetische Operationen anzuwenden, die innerhalb des aktuellen Kontexts für den aktiven Thread stattfinden. Ein alternativer Ansatz ist die Verwendung von Kontextmethoden zur Berechnung innerhalb eines bestimmten Kontexts. Die Methoden sind denen für dieDecimal-Klasse ähnlich und werden hier nur kurz wiedergegeben.- abs(x, /)¶
Gibt den Absolutwert von x zurück.
- add(x, y, /)¶
Gibt die Summe von x und y zurück.
- canonical(x, /)¶
Gibt dasselbe Decimal-Objekt x zurück.
- compare(x, y, /)¶
Vergleicht x und y numerisch.
- compare_signal(x, y, /)¶
Vergleicht die Werte der beiden Operanden numerisch.
- compare_total(x, y, /)¶
Vergleicht zwei Operanden anhand ihrer abstrakten Darstellung.
- compare_total_mag(x, y, /)¶
Vergleicht zwei Operanden anhand ihrer abstrakten Darstellung und ignoriert dabei das Vorzeichen.
- copy_abs(x, /)¶
Gibt eine Kopie von x zurück, bei der das Vorzeichen auf 0 gesetzt ist.
- copy_negate(x, /)¶
Gibt eine Kopie von x mit invertiertem Vorzeichen zurück.
- copy_sign(x, y, /)¶
Kopiert das Vorzeichen von y nach x.
- divide(x, y, /)¶
Gibt x geteilt durch y zurück.
- divide_int(x, y, /)¶
Gibt x geteilt durch y zurück, auf eine Ganzzahl gekürzt.
- divmod(x, y, /)¶
Teilt zwei Zahlen und gibt den ganzzahligen Teil des Ergebnisses zurück.
- exp(x, /)¶
Gibt
e ** xzurück.
- fma(x, y, z, /)¶
Gibt x multipliziert mit y plus z zurück.
- is_canonical(x, /)¶
Gibt
Truezurück, wenn x kanonisch ist, andernfallsFalse.
- is_finite(x, /)¶
Gibt
Truezurück, wenn x endlich ist, andernfallsFalse.
- is_infinite(x, /)¶
Gibt
Truezurück, wenn x unendlich ist, andernfallsFalse.
- is_nan(x, /)¶
Gibt
Truezurück, wenn x eine qNaN oder sNaN ist, andernfallsFalse.
- is_normal(x, /)¶
Gibt
Truezurück, wenn x eine normale Zahl ist, andernfallsFalse.
- is_qnan(x, /)¶
Gibt
Truezurück, wenn x eine quiet NaN ist, andernfallsFalse.
- is_signed(x, /)¶
Gibt
Truezurück, wenn x negativ ist, andernfallsFalse.
- is_snan(x, /)¶
Gibt
Truezurück, wenn x eine signaling NaN ist, andernfallsFalse.
- is_subnormal(x, /)¶
Gibt
Truezurück, wenn x subnormal ist, andernfallsFalse.
- is_zero(x, /)¶
Gibt
Truezurück, wenn x eine Null ist, andernfallsFalse.
- ln(x, /)¶
Gibt den natürlichen (Basis e) Logarithmus von x zurück.
- log10(x, /)¶
Gibt den Basis 10 Logarithmus von x zurück.
- logb(x, /)¶
Gibt den Exponenten der Größenordnung des MSD des Operanden zurück.
- logical_and(x, y, /)¶
Wendet die logische UND-Operation zwischen den Ziffern jedes Operanden an.
- logical_invert(x, /)¶
Invertiert alle Ziffern in x.
- logical_or(x, y, /)¶
Wendet die logische ODER-Operation zwischen den Ziffern jedes Operanden an.
- logical_xor(x, y, /)¶
Wendet die logische XOR-Operation zwischen den Ziffern jedes Operanden an.
- max(x, y, /)¶
Vergleicht zwei Werte numerisch und gibt das Maximum zurück.
- max_mag(x, y, /)¶
Vergleicht die Werte numerisch unter Ignorieren des Vorzeichens.
- min(x, y, /)¶
Vergleicht zwei Werte numerisch und gibt das Minimum zurück.
- min_mag(x, y, /)¶
Vergleicht die Werte numerisch unter Ignorieren des Vorzeichens.
- minus(x, /)¶
Minus entspricht dem unären Präfix-Minus-Operator in Python.
- multiply(x, y, /)¶
Gibt das Produkt von x und y zurück.
- next_minus(x, /)¶
Gibt die größte darstellbare Zahl zurück, die kleiner als x ist.
- next_plus(x, /)¶
Gibt die kleinste darstellbare Zahl zurück, die größer als x ist.
- next_toward(x, y, /)¶
Gibt die Zahl zurück, die x am nächsten liegt, in Richtung von y.
- normalize(x, /)¶
Reduziert x auf seine einfachste Form.
- number_class(x, /)¶
Gibt eine Angabe über die Klasse von x zurück.
- plus(x, /)¶
Plus entspricht dem unären Präfix-Plus-Operator in Python. Diese Operation wendet die Kontextpräzision und Rundung an, daher ist es **keine** Identitätsoperation.
- power(x, y, modulo=None)¶
Gibt
xhochyzurück, reduziert modulomodulo, falls angegeben.Mit zwei Argumenten wird
x**yberechnet. Wennxnegativ ist, mussyeine ganze Zahl sein. Das Ergebnis ist ungenau, es sei denn,yist eine ganze Zahl und das Ergebnis ist endlich und kann mit 'precision' Ziffern exakt dargestellt werden. Der Rundungsmodus des Kontexts wird verwendet. Ergebnisse sind in der Python-Version immer korrekt gerundet.Decimal(0) ** Decimal(0)ergibtInvalidOperation, und wennInvalidOperationnicht abgefangen wird, ergibt sichDecimal('NaN').Geändert in Version 3.3: Das C-Modul berechnet
power()anhand der korrekt gerundeten Funktionenexp()undln(). Das Ergebnis ist gut definiert, aber nur „fast immer korrekt gerundet“.Mit drei Argumenten wird
(x**y) % moduloberechnet. Für die Drei-Argument-Form gelten die folgenden Einschränkungen für die Argumente:Alle drei Argumente müssen ganze Zahlen sein.
ymuss nicht negativ sein.Mindestens eines von
xoderymuss ungleich Null sein.modulomuss ungleich Null sein und darf höchstens 'precision' Ziffern haben.
Der Wert, der sich aus
Context.power(x, y, modulo)ergibt, ist gleich dem Wert, der durch die Berechnung von(x**y) % modulomit unbegrenzter Genauigkeit erhalten würde, wird aber effizienter berechnet. Der Exponent des Ergebnisses ist Null, unabhängig von den Exponenten vonx,yundmodulo. Das Ergebnis ist immer exakt.
- quantize(x, y, /)¶
Gibt einen Wert zurück, der gleich x ist (gerundet) und den Exponenten von y hat.
- radix()¶
Gibt einfach 10 zurück, da dies Decimal ist, :)
- remainder(x, y, /)¶
Gibt den Rest einer ganzzahligen Division zurück.
Das Vorzeichen des Ergebnisses, falls ungleich Null, ist dasselbe wie das des ursprünglichen Dividenden.
- remainder_near(x, y, /)¶
Gibt
x - y * nzurück, wobei n die ganze Zahl ist, die dem exakten Wert vonx / yam nächsten liegt (wenn das Ergebnis 0 ist, hat es das Vorzeichen von x).
- rotate(x, y, /)¶
Gibt eine rotierte Kopie von x zurück, y mal.
- same_quantum(x, y, /)¶
Gibt
Truezurück, wenn die beiden Operanden denselben Exponenten haben.
- scaleb(x, y, /)¶
Gibt den ersten Operanden zurück, nachdem der zweite Wert zu seinem Exponenten addiert wurde.
- shift(x, y, /)¶
Gibt eine verschobene Kopie von x zurück, y mal.
- sqrt(x, /)¶
Quadratwurzel einer nicht-negativen Zahl mit Kontextpräzision.
- subtract(x, y, /)¶
Gibt die Differenz zwischen x und y zurück.
- to_eng_string(x, /)¶
Konvertiert in einen String, der eine Ingenieursschreibweise verwendet, wenn ein Exponent benötigt wird.
Die Ingenieursschreibweise hat einen Exponenten, der ein Vielfaches von 3 ist. Dies kann bis zu 3 Ziffern links vom Dezimalpunkt belassen und erfordert möglicherweise das Hinzufügen von ein oder zwei nachgestellten Nullen.
- to_integral_exact(x, /)¶
Rundet auf eine ganze Zahl.
- to_sci_string(x, /)¶
Konvertiert eine Zahl mit wissenschaftlicher Notation in einen String.
Konstanten¶
Die Konstanten in diesem Abschnitt sind nur für das C-Modul relevant. Sie sind aus Kompatibilitätsgründen auch in der reinen Python-Version enthalten.
32-Bit |
64-Bit |
|
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
- decimal.HAVE_THREADS¶
Der Wert ist
True. Veraltet, da Python jetzt immer Threads hat.Veraltet seit Version 3.9.
- decimal.HAVE_CONTEXTVAR¶
Der Standardwert ist
True. Wenn Python mit der Option--without-decimal-contextvarkonfiguriert wird, verwendet die C-Version einen Thread-lokalen anstelle eines Coroutine-lokalen Kontexts und der Wert istFalse. Dies ist in einigen verschachtelten Kontext-Szenarien geringfügig schneller.Hinzugefügt in Version 3.8.3.
Rundungsmodi¶
- decimal.ROUND_CEILING¶
Rundet in Richtung
Infinity.
- decimal.ROUND_DOWN¶
Rundet in Richtung Null.
- decimal.ROUND_FLOOR¶
Rundet in Richtung
-Infinity.
- decimal.ROUND_HALF_DOWN¶
Rundet auf die nächste Zahl, wobei Gleichstände in Richtung Null gehen.
- decimal.ROUND_HALF_EVEN¶
Rundet auf die nächste Zahl, wobei Gleichstände zur nächsten geraden Zahl gehen.
- decimal.ROUND_HALF_UP¶
Rundet auf die nächste Zahl, wobei Gleichstände vom Null weg gehen.
- decimal.ROUND_UP¶
Rundet weg von der Null.
- decimal.ROUND_05UP¶
Rundet weg von der Null, wenn die letzte Ziffer nach dem Runden zur Null hin 0 oder 5 wäre; sonst rundet zur Null hin.
Signale¶
Signale stellen Bedingungen dar, die während der Berechnung auftreten. Jedes entspricht einer Kontextflagge und einem Kontext-Trap-Schalter.
Die Kontextflagge wird gesetzt, wann immer die Bedingung angetroffen wird. Nach der Berechnung können die Flaggen zu Informationszwecken überprüft werden (z. B. um festzustellen, ob eine Berechnung exakt war). Stellen Sie nach der Überprüfung der Flaggen sicher, dass alle Flaggen gelöscht werden, bevor Sie mit der nächsten Berechnung beginnen.
Wenn der Trap-Schalter des Kontexts für das Signal gesetzt ist, wird die Bedingung eine Python-Ausnahme auslösen. Wenn beispielsweise der Trap für DivisionByZero gesetzt ist, wird eine Ausnahme DivisionByZero ausgelöst, wenn die Bedingung angetroffen wird.
- class decimal.Clamped¶
Der Exponent wurde angepasst, um die Darstellungseinschränkungen zu erfüllen.
Typischerweise tritt eine Beschränkung auf, wenn ein Exponent außerhalb der Grenzen
EminundEmaxdes Kontexts liegt. Wenn möglich, wird der Exponent durch Hinzufügen von Nullen zum Koeffizienten reduziert, um ihn anzupassen.
- class decimal.DecimalException¶
Basisklasse für andere Signale und eine Unterklasse von
ArithmeticError.
- class decimal.DivisionByZero¶
Signalisiert die Division einer nicht-unendlichen Zahl durch Null.
Kann bei Division, Modulo-Division oder beim Potenzieren einer Zahl mit negativer Potenz auftreten. Wenn dieses Signal nicht abgefangen wird, wird
Infinityoder-Infinitymit dem durch die Eingaben der Berechnung bestimmten Vorzeichen zurückgegeben.
- class decimal.Inexact¶
Zeigt an, dass eine Rundung stattgefunden hat und das Ergebnis nicht exakt ist.
Signalisiert, wenn Nicht-Null-Ziffern beim Runden verworfen wurden. Das gerundete Ergebnis wird zurückgegeben. Das Signal-Flag oder der Trap wird verwendet, um zu erkennen, wann Ergebnisse ungenau sind.
- class decimal.InvalidOperation¶
Eine ungültige Operation wurde durchgeführt.
Zeigt an, dass eine Operation angefordert wurde, die keinen Sinn ergibt. Wenn nicht abgefangen, wird
NaNzurückgegeben. Mögliche Ursachen sindInfinity - Infinity 0 * Infinity Infinity / Infinity x % 0 Infinity % x sqrt(-x) and x > 0 0 ** 0 x ** (non-integer) x ** Infinity
- class decimal.Overflow¶
Numerische Überlauf.
Zeigt an, dass der Exponent nach dem Runden größer als
Context.Emaxist. Wenn nicht abgefangen, hängt das Ergebnis vom Rundungsmodus ab, entweder indem es nach innen zur größten darstellbaren endlichen Zahl gezogen wird oder nach außen zuInfinitygerundet wird. In beiden Fällen werden auchInexactundRoundedsignalisiert.
- class decimal.Rounded¶
Es erfolgte eine Rundung, auch wenn möglicherweise keine Informationen verloren gingen.
Signalisiert, wann immer beim Runden Ziffern verworfen werden; auch wenn diese Ziffern Nullen sind (z. B. Runden von
5.00auf5.0). Wenn nicht abgefangen, wird das Ergebnis unverändert zurückgegeben. Dieses Signal wird verwendet, um den Verlust signifikanter Ziffern zu erkennen.
- class decimal.Subnormal¶
Der Exponent lag vor dem Runden unter
Emin.Tritt auf, wenn ein Operationsergebnis subnormal ist (der Exponent ist zu klein). Wenn nicht abgefangen, wird das Ergebnis unverändert zurückgegeben.
- class decimal.Underflow¶
Numerischer Unterlauf mit Ergebnis auf Null gerundet.
Tritt auf, wenn ein subnormales Ergebnis durch Rundung auf Null gesetzt wird.
InexactundSubnormalwerden ebenfalls signalisiert.
- class decimal.FloatOperation¶
Ermöglicht strengere Semantik für die Mischung von Gleitkommazahlen und Dezimalzahlen.
Wenn das Signal nicht abgefangen wird (Standard), ist die Mischung von Gleitkommazahlen und Dezimalzahlen im Konstruktor
Decimal,create_decimal()und allen Vergleichsoperatoren erlaubt. Sowohl Konvertierung als auch Vergleiche sind exakt. Jedes Vorkommen einer gemischten Operation wird stillschweigend durch Setzen vonFloatOperationin den Kontextflaggen aufgezeichnet. Explizite Konvertierungen mitfrom_float()odercreate_decimal_from_float()setzen die Flagge nicht.Andernfalls (das Signal wird abgefangen) sind nur Gleichheitsvergleiche und explizite Konvertierungen stillschweigend. Alle anderen gemischten Operationen lösen
FloatOperationaus.
Die folgende Tabelle fasst die Hierarchie der Signale zusammen
exceptions.ArithmeticError(exceptions.Exception)
DecimalException
Clamped
DivisionByZero(DecimalException, exceptions.ZeroDivisionError)
Inexact
Overflow(Inexact, Rounded)
Underflow(Inexact, Rounded, Subnormal)
InvalidOperation
Rounded
Subnormal
FloatOperation(DecimalException, exceptions.TypeError)
Hinweise zu Gleitkommazahlen¶
Minderung von Rundungsfehlern durch erhöhte Genauigkeit¶
Die Verwendung von dezimalen Gleitkommazahlen eliminiert den Dezimaldarstellungsfehler (wodurch 0.1 exakt dargestellt werden kann); einige Operationen können jedoch immer noch Rundungsfehler verursachen, wenn Nicht-Null-Ziffern die feste Genauigkeit überschreiten.
Die Auswirkungen von Rundungsfehlern können durch die Addition oder Subtraktion von sich fast aufhebenden Mengen verstärkt werden, was zu einem Verlust an Signifikanz führt. Knuth liefert zwei lehrreiche Beispiele, in denen gerundete Gleitkomma-Arithmetik mit unzureichender Genauigkeit zum Zusammenbruch der assoziativen und distributiven Eigenschaften der Addition führt.
# Examples from Seminumerical Algorithms, Section 4.2.2.
>>> from decimal import Decimal, getcontext
>>> getcontext().prec = 8
>>> u, v, w = Decimal(11111113), Decimal(-11111111), Decimal('7.51111111')
>>> (u + v) + w
Decimal('9.5111111')
>>> u + (v + w)
Decimal('10')
>>> u, v, w = Decimal(20000), Decimal(-6), Decimal('6.0000003')
>>> (u*v) + (u*w)
Decimal('0.01')
>>> u * (v+w)
Decimal('0.0060000')
Das Modul decimal ermöglicht die Wiederherstellung der Identitäten durch Erhöhung der Genauigkeit, um einen Verlust an Signifikanz zu vermeiden.
>>> getcontext().prec = 20
>>> u, v, w = Decimal(11111113), Decimal(-11111111), Decimal('7.51111111')
>>> (u + v) + w
Decimal('9.51111111')
>>> u + (v + w)
Decimal('9.51111111')
>>>
>>> u, v, w = Decimal(20000), Decimal(-6), Decimal('6.0000003')
>>> (u*v) + (u*w)
Decimal('0.0060000')
>>> u * (v+w)
Decimal('0.0060000')
Spezielle Werte¶
Das Zahlensystem für das Modul decimal bietet spezielle Werte, darunter NaN, sNaN, -Infinity, Infinity und zwei Nullen, +0 und -0.
Unendlichkeiten können direkt mit Decimal('Infinity') konstruiert werden. Sie können auch aus der Division durch Null entstehen, wenn das Signal DivisionByZero nicht abgefangen wird. Ebenso kann, wenn das Signal Overflow nicht abgefangen wird, Unendlichkeit aus Rundungen über die Grenzen der größten darstellbaren Zahl hinaus entstehen.
Die Unendlichkeiten sind vorzeichenbehaftet (afffin) und können in arithmetischen Operationen verwendet werden, wo sie als sehr große, unbestimmte Zahlen behandelt werden. Zum Beispiel ergibt die Addition einer Konstanten zur Unendlichkeit ein weiteres unendliches Ergebnis.
Einige Operationen sind unbestimmt und geben NaN zurück, oder wenn das Signal InvalidOperation abgefangen wird, lösen sie eine Ausnahme aus. Zum Beispiel gibt 0/0 NaN zurück, was "not a number" bedeutet. Diese Variante von NaN ist still und fließt nach der Erstellung durch andere Berechnungen und ergibt immer wieder ein anderes NaN. Dieses Verhalten kann für eine Reihe von Berechnungen nützlich sein, die gelegentlich fehlende Eingaben haben — es ermöglicht der Berechnung, fortzufahren, während bestimmte Ergebnisse als ungültig markiert werden.
Eine Variante ist sNaN, die eher signalisiert als nach jeder Operation still bleibt. Dies ist ein nützlicher Rückgabewert, wenn ein ungültiges Ergebnis eine Berechnung für eine Sonderbehandlung unterbrechen muss.
Das Verhalten der Vergleichsoperatoren von Python kann ein wenig überraschend sein, wenn eine NaN beteiligt ist. Ein Test auf Gleichheit, bei dem einer der Operanden eine stille oder signalisierende NaN ist, gibt immer False zurück (selbst bei Decimal('NaN')==Decimal('NaN')), während ein Test auf Ungleichheit immer True zurückgibt. Ein Versuch, zwei Dezimalzahlen mit einem der Operatoren <, <=, > oder >= zu vergleichen, löst das Signal InvalidOperation aus, wenn einer der Operanden eine NaN ist, und gibt False zurück, wenn dieses Signal nicht abgefangen wird. Beachten Sie, dass die General Decimal Arithmetic Specification das Verhalten direkter Vergleiche nicht vorschreibt; diese Regeln für Vergleiche, die eine NaN beinhalten, wurden aus dem IEEE 854-Standard übernommen (siehe Tabelle 3 in Abschnitt 5.7). Um eine strikte Einhaltung der Standards zu gewährleisten, verwenden Sie stattdessen die Methoden compare() und compare_signal().
Die vorzeichenbehafteten Nullen können aus Berechnungen entstehen, die einen Unterlauf haben. Sie behalten das Vorzeichen, das entstanden wäre, wenn die Berechnung mit höherer Genauigkeit durchgeführt worden wäre. Da ihre Magnitude Null ist, werden sowohl positive als auch negative Nullen als gleich behandelt und ihr Vorzeichen ist informativ.
Zusätzlich zu den beiden vorzeichenbehafteten Nullen, die zwar unterschiedlich, aber gleich sind, gibt es verschiedene Darstellungen von Null mit unterschiedlicher Genauigkeit, aber gleichem Wert. Daran muss man sich erst gewöhnen. Für ein Auge, das an normalisierte Gleitkommadarstellungen gewöhnt ist, ist es nicht sofort ersichtlich, dass die folgende Berechnung einen Wert ergibt, der gleich Null ist.
>>> 1 / Decimal('Infinity')
Decimal('0E-1000026')
Arbeiten mit Threads¶
Die Funktion getcontext() greift auf ein anderes Context-Objekt für jeden Thread zu. Separate Thread-Kontexte bedeuten, dass Threads Änderungen vornehmen können (z. B. getcontext().prec=10), ohne andere Threads zu beeinträchtigen.
Ebenso weist die Funktion setcontext() automatisch ihr Ziel dem aktuellen Thread zu.
Wenn setcontext() nicht vor getcontext() aufgerufen wurde, erstellt getcontext() automatisch einen neuen Kontext für die Verwendung im aktuellen Thread. Neue Kontextobjekte haben Standardwerte, die aus dem Objekt decimal.DefaultContext übernommen werden.
Die Flagge sys.flags.thread_inherit_context beeinflusst den Kontext für neue Threads. Wenn die Flagge falsch ist, starten neue Threads mit einem leeren Kontext. In diesem Fall erstellt getcontext() beim Aufruf ein neues Kontextobjekt und verwendet die Standardwerte von *DefaultContext*. Wenn die Flagge wahr ist, starten neue Threads mit einer Kopie des Kontexts des Aufrufers von threading.Thread.start().
Um die Standardwerte so zu steuern, dass jeder Thread die gleichen Werte in der gesamten Anwendung verwendet, modifizieren Sie direkt das Objekt *DefaultContext*. Dies sollte geschehen, *bevor* irgendwelche Threads gestartet werden, damit es keinen Race Condition zwischen Threads gibt, die getcontext() aufrufen. Zum Beispiel
# Set applicationwide defaults for all threads about to be launched
DefaultContext.prec = 12
DefaultContext.rounding = ROUND_DOWN
DefaultContext.traps = ExtendedContext.traps.copy()
DefaultContext.traps[InvalidOperation] = 1
setcontext(DefaultContext)
# Afterwards, the threads can be started
t1.start()
t2.start()
t3.start()
. . .
Rezepte¶
Hier sind einige Rezepte, die als Hilfsfunktionen dienen und Möglichkeiten zur Arbeit mit der Klasse Decimal demonstrieren
def moneyfmt(value, places=2, curr='', sep=',', dp='.',
pos='', neg='-', trailneg=''):
"""Convert Decimal to a money formatted string.
places: required number of places after the decimal point
curr: optional currency symbol before the sign (may be blank)
sep: optional grouping separator (comma, period, space, or blank)
dp: decimal point indicator (comma or period)
only specify as blank when places is zero
pos: optional sign for positive numbers: '+', space or blank
neg: optional sign for negative numbers: '-', '(', space or blank
trailneg:optional trailing minus indicator: '-', ')', space or blank
>>> d = Decimal('-1234567.8901')
>>> moneyfmt(d, curr='$')
'-$1,234,567.89'
>>> moneyfmt(d, places=0, sep='.', dp='', neg='', trailneg='-')
'1.234.568-'
>>> moneyfmt(d, curr='$', neg='(', trailneg=')')
'($1,234,567.89)'
>>> moneyfmt(Decimal(123456789), sep=' ')
'123 456 789.00'
>>> moneyfmt(Decimal('-0.02'), neg='<', trailneg='>')
'<0.02>'
"""
q = Decimal(10) ** -places # 2 places --> '0.01'
sign, digits, exp = value.quantize(q).as_tuple()
result = []
digits = list(map(str, digits))
build, next = result.append, digits.pop
if sign:
build(trailneg)
for i in range(places):
build(next() if digits else '0')
if places:
build(dp)
if not digits:
build('0')
i = 0
while digits:
build(next())
i += 1
if i == 3 and digits:
i = 0
build(sep)
build(curr)
build(neg if sign else pos)
return ''.join(reversed(result))
def pi():
"""Compute Pi to the current precision.
>>> print(pi())
3.141592653589793238462643383
"""
getcontext().prec += 2 # extra digits for intermediate steps
three = Decimal(3) # substitute "three=3.0" for regular floats
lasts, t, s, n, na, d, da = 0, three, 3, 1, 0, 0, 24
while s != lasts:
lasts = s
n, na = n+na, na+8
d, da = d+da, da+32
t = (t * n) / d
s += t
getcontext().prec -= 2
return +s # unary plus applies the new precision
def exp(x):
"""Return e raised to the power of x. Result type matches input type.
>>> print(exp(Decimal(1)))
2.718281828459045235360287471
>>> print(exp(Decimal(2)))
7.389056098930650227230427461
>>> print(exp(2.0))
7.38905609893
>>> print(exp(2+0j))
(7.38905609893+0j)
"""
getcontext().prec += 2
i, lasts, s, fact, num = 0, 0, 1, 1, 1
while s != lasts:
lasts = s
i += 1
fact *= i
num *= x
s += num / fact
getcontext().prec -= 2
return +s
def cos(x):
"""Return the cosine of x as measured in radians.
The Taylor series approximation works best for a small value of x.
For larger values, first compute x = x % (2 * pi).
>>> print(cos(Decimal('0.5')))
0.8775825618903727161162815826
>>> print(cos(0.5))
0.87758256189
>>> print(cos(0.5+0j))
(0.87758256189+0j)
"""
getcontext().prec += 2
i, lasts, s, fact, num, sign = 0, 0, 1, 1, 1, 1
while s != lasts:
lasts = s
i += 2
fact *= i * (i-1)
num *= x * x
sign *= -1
s += num / fact * sign
getcontext().prec -= 2
return +s
def sin(x):
"""Return the sine of x as measured in radians.
The Taylor series approximation works best for a small value of x.
For larger values, first compute x = x % (2 * pi).
>>> print(sin(Decimal('0.5')))
0.4794255386042030002732879352
>>> print(sin(0.5))
0.479425538604
>>> print(sin(0.5+0j))
(0.479425538604+0j)
"""
getcontext().prec += 2
i, lasts, s, fact, num, sign = 1, 0, x, 1, x, 1
while s != lasts:
lasts = s
i += 2
fact *= i * (i-1)
num *= x * x
sign *= -1
s += num / fact * sign
getcontext().prec -= 2
return +s
FAQ zu Dezimalzahlen¶
F. Es ist umständlich, decimal.Decimal('1234.5') einzugeben. Gibt es eine Möglichkeit, die Tipparbeit im interaktiven Interpreter zu minimieren?
A. Einige Benutzer kürzen den Konstruktor auf einen einzelnen Buchstaben
>>> D = decimal.Decimal
>>> D('1.23') + D('3.45')
Decimal('4.68')
F. In einer Festkomma-Anwendung mit zwei Dezimalstellen haben einige Eingaben viele Stellen und müssen gerundet werden. Andere sollen keine überzähligen Ziffern haben und müssen validiert werden. Welche Methoden sollten verwendet werden?
A. Die Methode quantize() rundet auf eine feste Anzahl von Dezimalstellen. Wenn der Trap Inexact gesetzt ist, ist er auch für die Validierung nützlich.
>>> TWOPLACES = Decimal(10) ** -2 # same as Decimal('0.01')
>>> # Round to two places
>>> Decimal('3.214').quantize(TWOPLACES)
Decimal('3.21')
>>> # Validate that a number does not exceed two places
>>> Decimal('3.21').quantize(TWOPLACES, context=Context(traps=[Inexact]))
Decimal('3.21')
>>> Decimal('3.214').quantize(TWOPLACES, context=Context(traps=[Inexact]))
Traceback (most recent call last):
...
Inexact: None
F. Wie kann ich nach Erhalt gültiger zweistelliger Eingaben diese Invariante in der gesamten Anwendung beibehalten?
A. Einige Operationen wie Addition, Subtraktion und Multiplikation mit einer Ganzzahl erhalten automatisch Festkomma. Andere Operationen wie Division und nicht-ganzzahlige Multiplikation ändern die Anzahl der Dezimalstellen und müssen anschließend mit einem Schritt quantize() folgen.
>>> a = Decimal('102.72') # Initial fixed-point values
>>> b = Decimal('3.17')
>>> a + b # Addition preserves fixed-point
Decimal('105.89')
>>> a - b
Decimal('99.55')
>>> a * 42 # So does integer multiplication
Decimal('4314.24')
>>> (a * b).quantize(TWOPLACES) # Must quantize non-integer multiplication
Decimal('325.62')
>>> (b / a).quantize(TWOPLACES) # And quantize division
Decimal('0.03')
Bei der Entwicklung von Festkomma-Anwendungen ist es praktisch, Funktionen zur Handhabung des quantize()-Schritts zu definieren.
>>> def mul(x, y, fp=TWOPLACES):
... return (x * y).quantize(fp)
...
>>> def div(x, y, fp=TWOPLACES):
... return (x / y).quantize(fp)
>>> mul(a, b) # Automatically preserve fixed-point
Decimal('325.62')
>>> div(b, a)
Decimal('0.03')
F. Es gibt viele Möglichkeiten, denselben Wert auszudrücken. Die Zahlen 200, 200.000, 2E2 und .02E+4 haben bei verschiedenen Genauigkeiten denselben Wert. Gibt es eine Möglichkeit, sie in einen einzigen erkennbaren kanonischen Wert zu transformieren?
A. Die Methode normalize() bildet alle äquivalenten Werte auf einen einzigen Repräsentanten ab.
>>> values = map(Decimal, '200 200.000 2E2 .02E+4'.split())
>>> [v.normalize() for v in values]
[Decimal('2E+2'), Decimal('2E+2'), Decimal('2E+2'), Decimal('2E+2')]
F. Wann tritt in einer Berechnung eine Rundung auf?
A. Sie tritt *nach* der Berechnung auf. Die Philosophie der Dezimalspezifikation ist, dass Zahlen als exakt betrachtet werden und unabhängig vom aktuellen Kontext erstellt werden. Sie können sogar eine höhere Genauigkeit haben als der aktuelle Kontext. Berechnungen verarbeiten diese exakten Eingaben, und dann wird die Rundung (oder andere Kontextoperationen) auf das *Ergebnis* der Berechnung angewendet.
>>> getcontext().prec = 5
>>> pi = Decimal('3.1415926535') # More than 5 digits
>>> pi # All digits are retained
Decimal('3.1415926535')
>>> pi + 0 # Rounded after an addition
Decimal('3.1416')
>>> pi - Decimal('0.00005') # Subtract unrounded numbers, then round
Decimal('3.1415')
>>> pi + 0 - Decimal('0.00005'). # Intermediate values are rounded
Decimal('3.1416')
F. Einige Dezimalwerte werden immer in exponentieller Notation ausgegeben. Gibt es eine Möglichkeit, eine nicht-exponentielle Darstellung zu erhalten?
A. Bei einigen Werten ist die exponentielle Notation die einzige Möglichkeit, die Anzahl der signifikanten Stellen im Koeffizienten auszudrücken. Zum Beispiel behält die Darstellung von 5.0E+3 als 5000 den Wert konstant, kann aber nicht die zweistellige Signifikanz des Originals anzeigen.
Wenn eine Anwendung die Verfolgung der Signifikanz nicht interessiert, ist es einfach, den Exponenten und die nachfolgenden Nullen zu entfernen, wodurch die Signifikanz verloren geht, aber der Wert unverändert bleibt.
>>> def remove_exponent(d):
... return d.quantize(Decimal(1)) if d == d.to_integral() else d.normalize()
>>> remove_exponent(Decimal('5E+3'))
Decimal('5000')
F. Gibt es eine Möglichkeit, eine normale Gleitkommazahl in eine Decimal zu konvertieren?
A. Ja, jede binäre Gleitkommazahl kann exakt als Dezimalzahl ausgedrückt werden, obwohl eine exakte Konvertierung mehr Genauigkeit erfordern kann, als die Intuition vermuten lässt.
>>> Decimal(math.pi)
Decimal('3.141592653589793115997963468544185161590576171875')
F. Wie kann ich bei einer komplexen Berechnung sicherstellen, dass ich aufgrund unzureichender Genauigkeit oder Rundungsanomalien kein fehlerhaftes Ergebnis erhalten habe?
A. Das Dezimalmodul erleichtert das Testen von Ergebnissen. Eine bewährte Methode ist, Berechnungen mit höherer Genauigkeit und verschiedenen Rundungsmodi erneut durchzuführen. Deutlich unterschiedliche Ergebnisse deuten auf unzureichende Genauigkeit, Probleme mit dem Rundungsmodus, schlecht konditionierte Eingaben oder einen numerisch instabilen Algorithmus hin.
F. Mir ist aufgefallen, dass die Kontextgenauigkeit auf die Ergebnisse von Operationen angewendet wird, aber nicht auf die Eingaben. Gibt es etwas, auf das man achten muss, wenn man Werte unterschiedlicher Genauigkeiten mischt?
A. Ja. Das Prinzip ist, dass alle Werte als exakt betrachtet werden und die Arithmetik mit diesen Werten ebenfalls exakt ist. Nur die Ergebnisse werden gerundet. Der Vorteil für Eingaben ist, dass "was Sie tippen, ist, was Sie bekommen". Ein Nachteil ist, dass die Ergebnisse seltsam aussehen können, wenn Sie vergessen, dass die Eingaben nicht gerundet wurden.
>>> getcontext().prec = 3
>>> Decimal('3.104') + Decimal('2.104')
Decimal('5.21')
>>> Decimal('3.104') + Decimal('0.000') + Decimal('2.104')
Decimal('5.20')
Die Lösung besteht darin, entweder die Genauigkeit zu erhöhen oder die Eingaben mithilfe der unären Plusoperation zu erzwingen.
>>> getcontext().prec = 3
>>> +Decimal('1.23456789') # unary plus triggers rounding
Decimal('1.23')
Alternativ können Eingaben bei der Erstellung mithilfe der Methode Context.create_decimal() gerundet werden.
>>> Context(prec=5, rounding=ROUND_DOWN).create_decimal('1.2345678')
Decimal('1.2345')
F. Ist die CPython-Implementierung für große Zahlen schnell?
A. Ja. In den CPython- und PyPy3-Implementierungen integrieren die C/CFFI-Versionen des Dezimalmoduls die Hochgeschwindigkeitsbibliothek libmpdec für exakt gerundete Dezimal-Gleitkomma-Arithmetik mit beliebiger Genauigkeit [1]. libmpdec verwendet die Karatsuba-Multiplikation für mittelgroße Zahlen und die Number Theoretic Transform für sehr große Zahlen.
Der Kontext muss für exakte Arithmetik mit beliebiger Genauigkeit angepasst werden. Emin und Emax sollten immer auf die maximalen Werte gesetzt werden, clamp sollte immer 0 sein (Standard). Das Setzen von prec erfordert etwas Sorgfalt.
Der einfachste Ansatz zum Ausprobieren von Bignum-Arithmetik ist die Verwendung des Maximalwerts für prec als auch [2]
>>> setcontext(Context(prec=MAX_PREC, Emax=MAX_EMAX, Emin=MIN_EMIN))
>>> x = Decimal(2) ** 256
>>> x / 128
Decimal('904625697166532776746648320380374280103671755200316906558262375061821325312')
Für ungenaue Ergebnisse ist MAX_PREC auf 64-Bit-Plattformen viel zu groß und der verfügbare Speicher reicht nicht aus.
>>> Decimal(1) / 3
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
MemoryError
Auf Systemen mit Überbuchung (z. B. Linux) ist ein ausgefeilterer Ansatz, prec an die Menge des verfügbaren RAM anzupassen. Angenommen, Sie haben 8 GB RAM und erwarten 10 gleichzeitige Operanden, die jeweils maximal 500 MB verbrauchen.
>>> import sys
>>>
>>> # Maximum number of digits for a single operand using 500MB in 8-byte words
>>> # with 19 digits per word (4-byte and 9 digits for the 32-bit build):
>>> maxdigits = 19 * ((500 * 1024**2) // 8)
>>>
>>> # Check that this works:
>>> c = Context(prec=maxdigits, Emax=MAX_EMAX, Emin=MIN_EMIN)
>>> c.traps[Inexact] = True
>>> setcontext(c)
>>>
>>> # Fill the available precision with nines:
>>> x = Decimal(0).logical_invert() * 9
>>> sys.getsizeof(x)
524288112
>>> x + 2
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
decimal.Inexact: [<class 'decimal.Inexact'>]
Im Allgemeinen (und insbesondere auf Systemen ohne Überbuchung) wird empfohlen, die Grenzen noch enger abzuschätzen und den Trap für Inexact zu setzen, wenn erwartet wird, dass alle Berechnungen exakt sind.