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.1 und 2.2 keine exakte Darstellung in binärer Gleitkommaarithmetik. Endbenutzer erwarten typischerweise nicht, dass 1.1 + 2.2 als 3.3000000000000003 angezeigt 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.3 exakt gleich Null. In binärer Gleitkommaarithmetik ist das Ergebnis 5.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.20 2.50 ergibt. 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 ergibt 1.3 * 1.2 1.56, während 1.30 * 1.20 1.5600 ergibt.

  • 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

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 float oder ein anderes Decimal-Objekt sein. Wenn kein value angegeben ist, wird Decimal('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 digit oben 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 beispielsweise inf, Inf, INFINITY und iNfINity allesamt akzeptable Schreibweisen für positive Unendlichkeit.

Wenn value ein Tupel ist, sollte es drei Komponenten haben: ein Vorzeichen (0 für positiv oder 1 für negativ), ein Tupel von Ziffern und einen ganzzahligen Exponenten. Zum Beispiel gibt Decimal((0, (1, 4, 1, 4), -3)) Decimal('1.414') zurück.

Wenn value eine float ist, wird der binäre Gleitkommawert verlustfrei in seine exakte dezimale Entsprechung umgewandelt. Diese Umwandlung kann oft 53 oder mehr Ziffern Genauigkeit erfordern. Zum Beispiel konvertiert Decimal(float('1.1')) zu Decimal('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 InvalidOperation abfängt, wird eine Ausnahme ausgelöst; andernfalls gibt der Konstruktor eine neue Dezimalzahl mit dem Wert NaN zurü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 Trap FloatOperation gesetzt 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 float und int. 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 (wie float oder int) 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ät x == (x // y) * y + x % y zu erhalten.

>>> -7 // 4
-2
>>> Decimal(-7) // Decimal(4)
Decimal('-1')

Die Operatoren % und // implementieren die Operationen remainder und divide-integer (jeweils) gemäß der Spezifikation.

Dezimalobjekte können im Allgemeinen nicht mit Fließkommazahlen oder Instanzen von fractions.Fraction in arithmetischen Operationen kombiniert werden: Der Versuch, eine Decimal zu einer float hinzuzufügen, löst beispielsweise einen TypeError aus. Es ist jedoch möglich, Pythons Vergleichsoperatoren zu verwenden, um eine Decimal-Instanz x mit einer anderen Zahl y zu 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 gegebene Decimal-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ür Decimal-Instanzen. Zwei Decimal-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, und Decimal('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 zu x.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**x für die gegebene Zahl zurück. Das Ergebnis wird mit dem ROUND_HALF_EVEN Rundungsmodus 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 float oder int akzeptiert.

Hinweis: Decimal.from_float(0.1) ist nicht dasselbe wie Decimal('0.1'). Da 0.1 in binärer Gleitkommadarstellung nicht exakt darstellbar ist, wird der Wert als nächstgelegener darstellbarer Wert gespeichert, der 0x1.999999999999ap-4 ist. Dieser äquivalente Wert in Dezimal ist 0.1000000000000000055511151231257827021181583404541015625.

Hinweis

Ab Python 3.2 kann eine Decimal-Instanz auch direkt aus einem float erstellt werden.

>>> 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, int oder Decimal akzeptiert, 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 True zurück, wenn das Argument kanonisch ist, und False andernfalls. Derzeit ist eine Decimal-Instanz immer kanonisch, daher gibt diese Operation immer True zurück.

is_finite()

Gibt True zurück, wenn das Argument eine endliche Zahl ist, und False, wenn das Argument eine Unendlichkeit oder NaN ist.

is_infinite()

Gibt True zurück, wenn das Argument entweder positiv oder negativ unendlich ist, und False andernfalls.

is_nan()

Gibt True zurück, wenn das Argument ein (quiet oder signaling) NaN ist, und False andernfalls.

is_normal(context=None)

Gibt True zurück, wenn das Argument eine normale endliche Zahl ist. Gibt False zurück, wenn das Argument Null, subnormal, unendlich oder ein NaN ist.

is_qnan()

Gibt True zurück, wenn das Argument ein Quiet NaN ist, und False andernfalls.

is_signed()

Gibt True zurück, wenn das Argument ein negatives Vorzeichen hat, und False andernfalls. Beachten Sie, dass Nullen und NaNs beide Vorzeichen tragen können.

is_snan()

Gibt True zurück, wenn das Argument ein Signaling NaN ist, und False andernfalls.

is_subnormal(context=None)

Gibt True zurück, wenn das Argument subnormal ist, und False andernfalls.

is_zero()

Gibt True zurück, wenn das Argument ein (positives oder negatives) Null ist, und False andernfalls.

ln(context=None)

Gibt den natürlichen (Basis e) Logarithmus des Operanden zurück. Das Ergebnis wird mit dem ROUND_HALF_EVEN Rundungsmodus korrekt gerundet.

log10(context=None)

Gibt den Logarithmus zur Basis zehn des Operanden zurück. Das Ergebnis wird mit dem ROUND_HALF_EVEN Rundungsmodus 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, wird Decimal('-Infinity') zurückgegeben und das Flag DivisionByZero gesetzt. Wenn der Operand unendlich ist, wird Decimal('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 ziffernweise and der 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 ziffernweise or der 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 und NaN-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 und NaN-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') und Decimal('0.321000e+2') beide zu dem äquivalenten Wert Decimal('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 reduce bekannt.

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 InvalidOperation signalisiert. 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 rounding bestimmt, falls angegeben, andernfalls durch das gegebene Argument context; 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 Emax oder kleiner als Etiny() ist.

radix()

Gibt Decimal(10) zurück, die Radix (Basis), in der die Decimal-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 % other dadurch, dass das Vorzeichen des Rests so gewählt wird, dass sein absoluter Wert minimiert wird. Genauer gesagt ist der Rückgabewert self - n * other, wobei n die nächste ganze Zahl zum exakten Wert von self / other ist, 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 NaN sind.

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**other zurü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') zu Decimal('1.23E+3').

to_integral(rounding=None, context=None)

Identisch mit der Methode to_integral_value(). Der Name to_integral wurde zur Kompatibilität mit älteren Versionen beibehalten.

to_integral_exact(rounding=None, context=None)

Auf die nächste Ganzzahl runden, wobei bei Rundung entsprechend Inexact oder Rounded signalisiert wird. Der Rundungsmodus wird durch den Parameter rounding bestimmt, falls angegeben, andernfalls durch den angegebenen context. 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 Inexact oder Rounded zu 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 None ist, wird die nächste int zu number zurückgegeben, wobei bei Gleichstand zur nächsten geraden Zahl gerundet wird und der Rundungsmodus des Decimal-Kontexts ignoriert wird. Löst OverflowError aus, wenn number eine Unendlichkeit ist, oder ValueError, wenn es sich um eine (ruhige oder signalisierende) NaN handelt.

Wenn ndigits ein int ist, wird der Rundungsmodus des Kontexts beachtet und ein Decimal, das number auf das nächste Vielfache von Decimal('1E-ndigits') gerundet darstellt, zurückgegeben; in diesem Fall ist round(number, ndigits) äquivalent zu self.quantize(Decimal('1E-ndigits')). Gibt Decimal('NaN') zurück, wenn number eine ruhige NaN ist. Löst InvalidOperation aus, 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älle

  • wenn 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 TypeError aus, wenn kwargs ein Attribut liefert, das Context nicht unterstützt. Löst entweder TypeError oder ValueError aus, 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_UP eingestellt. Alle Flags sind gelöscht. Alle Traps sind aktiviert (werden als Ausnahmen behandelt) außer Inexact, Rounded und Subnormal.

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_EVEN eingestellt. 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 NaN oder Infinity bevorzugen. 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 Context als 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 Konstruktor Context erstellt 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_EVEN und aktivierte Traps für Overflow, InvalidOperation und DivisionByZero.

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 None ist, werden die Standardwerte aus DefaultContext kopiert. Wenn das Feld flags nicht angegeben oder None ist, 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 0 oder 1 (Standard). Wenn auf 1 gesetzt, werden Exponenten mit einem Großbuchstaben E ausgegeben; andernfalls wird ein Kleinbuchstabe e verwendet: Decimal('6.02e+23').

clamp

Entweder 0 (Standard) oder 1. Wenn auf 1 gesetzt, ist der Exponent e einer in diesem Kontext darstellbaren Decimal-Instanz streng auf den Bereich Emin - prec + 1 <= e <= Emax - prec + 1 beschränkt. Wenn clamp 0 ist, gilt eine schwächere Bedingung: Der angepasste Exponent der Decimal-Instanz ist höchstens Emax. Wenn clamp 1 ist, 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 1 ermöglicht Kompatibilität mit den Festbreiten-Dezimal-Austauschformaten, die in IEEE 754 spezifiziert sind.

Die Klasse Context definiert 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ür Decimal (mit Ausnahme der Methoden adjusted() und as_tuple()) eine entsprechende Context-Methode. Zum Beispiel ist für eine Context-Instanz C und eine Decimal-Instanz x, C.exp(x) äquivalent zu x.exp(context=C). Jede Context-Methode akzeptiert eine Python-Ganzzahl (eine Instanz von int) überall dort, wo eine Decimal-Instanz akzeptiert wird.

clear_flags()

Setzt alle Flags auf 0 zurück.

clear_traps()

Setzt alle Traps auf 0 zurü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 Decimal werden 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 + 1 ist, was der minimale Exponentenwert für subnormale Ergebnisse ist. Wenn ein Unterlauf auftritt, wird der Exponent auf Etiny gesetzt.

Etop()

Gibt einen Wert zurück, der gleich Emax - prec + 1 ist.

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 die Decimal-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 ** x zurück.

fma(x, y, z, /)

Gibt x multipliziert mit y plus z zurück.

is_canonical(x, /)

Gibt True zurück, wenn x kanonisch ist, andernfalls False.

is_finite(x, /)

Gibt True zurück, wenn x endlich ist, andernfalls False.

is_infinite(x, /)

Gibt True zurück, wenn x unendlich ist, andernfalls False.

is_nan(x, /)

Gibt True zurück, wenn x eine qNaN oder sNaN ist, andernfalls False.

is_normal(x, /)

Gibt True zurück, wenn x eine normale Zahl ist, andernfalls False.

is_qnan(x, /)

Gibt True zurück, wenn x eine quiet NaN ist, andernfalls False.

is_signed(x, /)

Gibt True zurück, wenn x negativ ist, andernfalls False.

is_snan(x, /)

Gibt True zurück, wenn x eine signaling NaN ist, andernfalls False.

is_subnormal(x, /)

Gibt True zurück, wenn x subnormal ist, andernfalls False.

is_zero(x, /)

Gibt True zurück, wenn x eine Null ist, andernfalls False.

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 x hoch y zurück, reduziert modulo modulo, falls angegeben.

Mit zwei Argumenten wird x**y berechnet. Wenn x negativ ist, muss y eine ganze Zahl sein. Das Ergebnis ist ungenau, es sei denn, y ist 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) ergibt InvalidOperation, und wenn InvalidOperation nicht abgefangen wird, ergibt sich Decimal('NaN').

Geändert in Version 3.3: Das C-Modul berechnet power() anhand der korrekt gerundeten Funktionen exp() und ln(). Das Ergebnis ist gut definiert, aber nur „fast immer korrekt gerundet“.

Mit drei Argumenten wird (x**y) % modulo berechnet. Für die Drei-Argument-Form gelten die folgenden Einschränkungen für die Argumente:

  • Alle drei Argumente müssen ganze Zahlen sein.

  • y muss nicht negativ sein.

  • Mindestens eines von x oder y muss ungleich Null sein.

  • modulo muss 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) % modulo mit unbegrenzter Genauigkeit erhalten würde, wird aber effizienter berechnet. Der Exponent des Ergebnisses ist Null, unabhängig von den Exponenten von x, y und modulo. 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 * n zurück, wobei n die ganze Zahl ist, die dem exakten Wert von x / y am 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 True zurü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.MAX_PREC

425000000

999999999999999999

decimal.MAX_EMAX

425000000

999999999999999999

decimal.MIN_EMIN

-425000000

-999999999999999999

decimal.MIN_ETINY

-849999999

-1999999999999999997

decimal.IEEE_CONTEXT_MAX_BITS

256

512

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-contextvar konfiguriert wird, verwendet die C-Version einen Thread-lokalen anstelle eines Coroutine-lokalen Kontexts und der Wert ist False. 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 Emin und Emax des 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 Infinity oder -Infinity mit 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 NaN zurückgegeben. Mögliche Ursachen sind

Infinity - 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.Emax ist. 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 zu Infinity gerundet wird. In beiden Fällen werden auch Inexact und Rounded signalisiert.

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.00 auf 5.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. Inexact und Subnormal werden 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 von FloatOperation in den Kontextflaggen aufgezeichnet. Explizite Konvertierungen mit from_float() oder create_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 FloatOperation aus.

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.