decimal — Decimal aritmetik med fasta och flytande kommatecken

Källkod: Lib/decimal.py


Modulen decimal ger stöd för snabb, korrekt avrundad decimal aritmetik med flyttal. Den erbjuder flera fördelar jämfört med datatypen float:

  • Decimal ”är baserat på en flyttalsmodell som utformades med människor i åtanke och som nödvändigtvis har en överordnad vägledande princip - datorer måste tillhandahålla en aritmetik som fungerar på samma sätt som den aritmetik som människor lär sig i skolan.” – Utdrag ur specifikationen för decimal aritmetik.

  • Decimaltal kan representeras exakt. Däremot har tal som 1,1 och 2,2 inte exakta representationer i binär flyttal. Slutanvändare förväntar sig vanligtvis inte att 1,1 + 2,2 ska visas som 3,3000000000000003 som det gör med binär flyttal.

  • Exaktheten överförs till aritmetik. I decimal flyttal är 0.1 + 0.1 + 0.1 - 0.3 exakt lika med noll. I binär flyttal blir resultatet 5.5511151231257827e-017. Även om skillnaderna är nära noll förhindrar de tillförlitlig jämlikhetstestning och skillnaderna kan ackumuleras. Av denna anledning föredras decimal i bokföringsapplikationer som har strikta jämlikhetsinvarianter.

  • Decimalmodulen innehåller ett begrepp om signifikanta ställen så att 1,30 + 1,20 är 2,50. Den efterföljande nollan behålls för att indikera signifikans. Detta är den gängse presentationen för monetära tillämpningar. Vid multiplikation används enligt ”skolboken” alla siffror i multiplikanden. Till exempel ger 1,3 * 1,2 1,56 medan 1,30 * 1,20 ger 1,5600.

  • Till skillnad från maskinvarubaserad binär flyttalsräkning har decimalmodulen en precision som kan ändras av användaren (standard är 28 enheter) och som kan vara så stor som behövs för ett visst problem:

    >>> from decimal import *
    >>> getcontext().prec = 6
    >>> Decimal(1) / Decimal(7)
    Decimal('0.142857')
    >>> getcontext().prec = 28
    >>> Decimal(1) / Decimal(7)
    Decimal('0.1428571428571428571428571429')
    
  • Både binär och decimal flyttal implementeras i enlighet med publicerade standarder. Medan den inbyggda float-typen bara visar en blygsam del av sina möjligheter, visar decimalmodulen alla nödvändiga delar av standarden. När det behövs har programmeraren full kontroll över avrundning och signalhantering. Detta inkluderar ett alternativ för att genomdriva exakt aritmetik genom att använda undantag för att blockera alla inexakta operationer.

  • Decimalmodulen utformades för att ”utan fördomar stödja både exakt oavrundad decimalaritmetik (ibland kallad fastpunktsaritmetik) och avrundad flyttalsaritmetik” – Utdrag ur specifikationen för decimalaritmetik.

Modulens design är centrerad kring tre koncept: decimaltalet, sammanhanget för aritmetik och signaler.

Ett decimaltal är oföränderligt. Det har ett tecken, koefficientsiffror och en exponent. För att bevara signifikansen trunkeras inte nollorna i koefficientsiffrorna. Decimaltal innehåller också specialvärden som Infinity, -Infinity och NaN. Standarden skiljer också mellan -0 och +0.

Kontexten för aritmetik är en miljö som anger precision, avrundningsregler, gränser för exponenter, flaggor som anger resultatet av operationer och trap enablers som avgör om signaler ska behandlas som undantag. Avrundningsalternativ inkluderar ROUND_CEILING, ROUND_DOWN, ROUND_FLOOR, ROUND_HALF_DOWN, ROUND_HALF_EVEN, ROUND_HALF_UP, ROUND_UP och ROUND_05UP.

Signaler är grupper av exceptionella förhållanden som uppstår under beräkningarnas gång. Beroende på applikationens behov kan signaler ignoreras, betraktas som information eller behandlas som undantag. Signalerna i decimalmodulen är: Clamped, InvalidOperation, DivisionByZero, Inexact, Rounded, Subnormal, Overflow, Underflow och FloatOperation.

För varje signal finns det en flagga och en fällaktiverare. När en signal påträffas sätts dess flagga till ett, och om trap enabler sätts till ett utlöses ett undantag. Flaggor är ”sticky”, så användaren måste återställa dem innan han/hon övervakar en beräkning.

Se även

Handledning för snabbstart

Den vanliga starten för att använda decimaler är att importera modulen, se den aktuella kontexten med getcontext() och, om nödvändigt, ange nya värden för precision, avrundning eller aktiverade fällor:

>>> 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

Decimalinstanser kan konstrueras från heltal, strängar, flyttal eller tupler. Konstruktion från ett heltal eller en float utför en exakt konvertering av värdet för det heltalet eller floaten. Decimaltal innehåller specialvärden som NaN som står för ”Not a number”, positiva och negativa Infinity, och -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')

Om signalen FloatOperation är fångad, kommer oavsiktlig blandning av decimaler och flyttal i konstruktörer eller orderjämförelser att ge upphov till ett undantag:

>>> 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

Tillagd i version 3.3.

Betydelsen av en ny decimal bestäms enbart av antalet inmatade siffror. Kontextens precision och avrundning spelar bara in under aritmetiska operationer.

>>> 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')

Om de interna gränserna för C-versionen överskrids, ger konstruktionen av en decimal InvalidOperation:

>>> Decimal("1e9999999999999999999")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
decimal.InvalidOperation: [<class 'decimal.InvalidOperation'>]

Ändrad i version 3.3.

Decimaler samverkar bra med mycket av resten av Python. Här är en liten flygande cirkus med decimala flyttal:

>>> 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')

Och vissa matematiska funktioner är också tillgängliga för Decimal:

>>> 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')

Metoden quantize() avrundar ett tal till en fast exponent. Denna metod är användbar för monetära applikationer som ofta avrundar resultat till ett fast antal enheter:

>>> Decimal('7.325').quantize(Decimal('.01'), rounding=ROUND_DOWN)
Decimal('7.32')
>>> Decimal('7.325').quantize(Decimal('1.'), rounding=ROUND_UP)
Decimal('8')

Som visas ovan får funktionen getcontext() tillgång till det aktuella sammanhanget och gör det möjligt att ändra inställningarna. Detta tillvägagångssätt uppfyller behoven i de flesta applikationer.

För mer avancerat arbete kan det vara användbart att skapa alternativa kontexter med hjälp av Context()-konstruktören. För att göra en alternativ kontext aktiv, använd funktionen setcontext().

I enlighet med standarden tillhandahåller modulen decimal två standardkontexter som är färdiga att använda, BasicContext och ExtendedContext. Den förstnämnda är speciellt användbar för felsökning eftersom många av fällorna är aktiverade:

>>> 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

Kontexter har också signalflaggor för övervakning av exceptionella förhållanden som uppstår under beräkningar. Flaggorna förblir inställda tills de uttryckligen rensas, så det är bäst att rensa flaggorna före varje uppsättning av övervakade beräkningar genom att använda metoden clear_flags().

>>> 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=[])

Posten flags visar att den rationella approximationen av pi avrundades (siffror utanför kontextprecisionen kastades bort) och att resultatet är inexakt (några av de bortkastade siffrorna var andra än noll).

Enskilda fällor ställs in med hjälp av ordlistan i attributet traps i en kontext:

>>> 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

De flesta program justerar den aktuella kontexten endast en gång, i början av programmet. Och i många applikationer konverteras data till Decimal med en enda cast inuti en loop. När kontexten är inställd och decimaler skapade, manipulerar huvuddelen av programmet data på samma sätt som med andra numeriska Python-typer.

Decimala objekt

class decimal.Decimal(value='0', context=None)

Konstruera ett nytt Decimal-objekt baserat på värde.

value kan vara ett heltal, en sträng, en tupel, float eller ett annat Decimal-objekt. Om inget värde anges returneras Decimal('0'). Om värde är en sträng bör den överensstämma med den decimala numeriska strängsyntaxen efter att inledande och avslutande blankstegstecken, samt understrykningstecken, har tagits bort:

tecken ::= '+' | '-'
siffra ::= '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'
indikator ::= 'e' | 'E'
siffror ::= siffra [siffra]...
decimal-del ::= siffror '.' [siffror] | ['.'] siffror
exponent-del ::= indikator [tecken] siffror
infinity ::= 'Oändlighet' | 'Inf'
nan ::= 'NaN' [siffror] | 'sNaN' [siffror]
numeriskt värde ::= decimaldel [exponentdel] | oändlighet
numerisk-sträng ::= [tecken] numeriskt-värde | [tecken] nan

Andra Unicode decimalsiffror är också tillåtna där digit visas ovan. Dessa inkluderar decimalsiffror från olika andra alfabet (till exempel arabisk-indiska och Devanāgarī-siffror) tillsammans med fullbreddssiffrorna '\uff10 till '\uff19. Versal är inte signifikant, så till exempel inf, Inf, INFINITY och iNfINity är alla acceptabla stavningar för positiv oändlighet.

Om värde är en tuple ska den ha tre komponenter, ett tecken (0 för positiv eller 1 för negativ), en tuple av siffror och en heltalsexponent. Till exempel ger Decimal((0, (1, 4, 1, 4), -3)) Decimal('1.414').

Om värde är en float konverteras det binära flyttalsvärdet förlustfritt till sin exakta decimala motsvarighet. Denna konvertering kan ofta kräva 53 eller fler precisionssiffror. Till exempel konverterar Decimal(float('1.1')) till Decimal('1.100000000000000088817841970012523233890533447265625').

Precisionen i kontexten påverkar inte hur många siffror som lagras. Det bestäms uteslutande av antalet siffror i värdet. Till exempel, Decimal('3.00000') registrerar alla fem nollor även om kontextprecisionen bara är tre.

Syftet med argumentet context är att bestämma vad som ska göras om value är en felformad sträng. Om kontexten fångar InvalidOperation, väcks ett undantag; i annat fall returnerar konstruktören en ny Decimal med värdet NaN.

När Decimal-objekt har konstruerats är de oföränderliga.

Ändrad i version 3.2: Argumentet till konstruktören får nu vara en float-instans.

Ändrad i version 3.3: float-argument ger upphov till ett undantag om FloatOperation-fällan är inställd. Som standard är fällan avstängd.

Ändrad i version 3.6: Underscores är tillåtna för gruppering, som med integral- och flyttalslitteraler i kod.

Decimala flyttalsobjekt delar många egenskaper med de andra inbyggda numeriska typerna, t.ex. float och int. Alla vanliga matematiska operationer och specialmetoder gäller. På samma sätt kan decimalobjekt kopieras, betas, skrivas ut, användas som ordboksnycklar, användas som set-element, jämföras, sorteras och tvingas till en annan typ (t.ex. float eller int).

Det finns några små skillnader mellan aritmetik på decimalobjekt och aritmetik på heltal och flyttal. När restoperatorn % används på decimalobjekt är resultatets tecken tecknet på divisorn i stället för tecknet på divisorn:

>>> (-7) % 4
1
>>> Decimal(-7) % Decimal(4)
Decimal('-3')

Operatorn för heltalsdivision // fungerar på samma sätt och returnerar heltalsdelen av den verkliga kvoten (trunkerad mot noll) i stället för dess golv, så att den vanliga identiteten x == (x // y) * y + x % y bevaras:

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

Operatorerna % och // implementerar operationerna remainder respektive divide-integer enligt beskrivningen i specifikationen.

Decimalobjekt kan i allmänhet inte kombineras med float eller instanser av fractions.Fraction i aritmetiska operationer: ett försök att lägga till en Decimal till en float, till exempel, kommer att ge upphov till ett TypeError. Det är dock möjligt att använda Pythons jämförelseoperatorer för att jämföra en Decimal-instans x med ett annat tal y. Detta undviker förvirrande resultat när man gör jämlikhetsjämförelser mellan tal av olika typer.

Ändrad i version 3.2: Jämförelser av blandade typer mellan Decimal-instanser och andra numeriska typer stöds nu fullt ut.

Förutom de numeriska standardegenskaperna har decimala flyttalsobjekt också ett antal specialiserade metoder:

adjusted()

Returnerar den justerade exponenten efter att koefficientens högra siffror har flyttats ut tills endast den första siffran återstår: Decimal('321e+5').adjusted() returnerar sju. Används för att bestämma positionen för den mest signifikanta siffran i förhållande till decimaltecknet.

as_integer_ratio()

Returnerar ett par (n, d) av heltal som representerar den givna Decimal-instansen som ett bråk, i lägsta termer och med en positiv nämnare:

>>> Decimal('-3.14').as_integer_ratio()
(-157, 50)

Omvandlingen är exakt. Ge upphov till OverflowError för oändligheter och ValueError för NaNs.

Tillagd i version 3.6.

as_tuple()

Returnera en named tuple representation av talet: DecimalTuple(sign, digits, exponent).

canonical()

Returnerar den kanoniska kodningen av argumentet. För närvarande är kodningen av en Decimal-instans alltid kanonisk, så denna operation returnerar sitt argument oförändrat.

compare(other, context=None)

Jämför värdena för två decimalinstanser. compare() returnerar en decimalinstans, och om någon av operanderna är ett NaN blir resultatet ett NaN:

a eller b är en NaN ==> Decimal('NaN')
a < b ==> Decimal('-1')
a == b ==> Decimal('0')
a > b ==> Decimal('1')
compare_signal(other, context=None)

Denna operation är identisk med metoden compare(), förutom att alla NaN signalerar. Det vill säga, om ingen av operanderna är ett signalerande NaN, behandlas varje tyst NaN-operand som om det vore ett signalerande NaN.

compare_total(other, context=None)

Jämför två operander med hjälp av deras abstrakta representation snarare än deras numeriska värde. Liknar metoden compare(), men resultatet ger en total ordning på Decimal-instanser. Två Decimal-instanser med samma numeriska värde men olika representationer jämförs ojämlikt i denna ordning:

>>> Decimal('12.0').compare_total(Decimal('12'))
Decimal('-1')

Tysta och signalerande NaNs ingår också i den totala ordningen. Resultatet av denna funktion är Decimal('0') om båda operanderna har samma representation, Decimal('-1') om den första operanden är lägre i den totala ordningen än den andra, och Decimal('1') om den första operanden är högre i den totala ordningen än den andra operanden. Se specifikationen för detaljer om den totala ordningen.

Denna operation påverkas inte av kontexten och är tyst: inga flaggor ändras och ingen avrundning utförs. Som ett undantag kan C-versionen ge upphov till InvalidOperation om den andra operanden inte kan konverteras exakt.

compare_total_mag(other, context=None)

Jämför två operander med hjälp av deras abstrakta representation i stället för deras värde som i compare_total(), men ignorerar tecknet för varje operand. x.compare_total_mag(y) är ekvivalent med x.copy_abs().compare_total(y.copy_abs()).

Denna operation påverkas inte av kontexten och är tyst: inga flaggor ändras och ingen avrundning utförs. Som ett undantag kan C-versionen ge upphov till InvalidOperation om den andra operanden inte kan konverteras exakt.

conjugate()

Returnerar bara self, denna metod är endast till för att uppfylla Decimal Specification.

copy_abs()

Returnerar argumentets absoluta värde. Denna operation påverkas inte av kontexten och är tyst: inga flaggor ändras och ingen avrundning utförs.

copy_negate()

Returnerar negationen av argumentet. Denna operation påverkas inte av kontexten och är tyst: inga flaggor ändras och ingen avrundning utförs.

copy_sign(other, context=None)

Returnerar en kopia av det första operandet med tecknet satt till samma som tecknet för det andra operandet. Till exempel

>>> Decimal('2.3').copy_sign(Decimal('-1.5'))
Decimal('-2.3')

Denna operation påverkas inte av kontexten och är tyst: inga flaggor ändras och ingen avrundning utförs. Som ett undantag kan C-versionen ge upphov till InvalidOperation om den andra operanden inte kan konverteras exakt.

exp(context=None)

Returnerar värdet av den (naturliga) exponentialfunktionen e**x vid det angivna talet. Resultatet avrundas korrekt med hjälp av avrundningsläget ROUND_HALF_EVEN.

>>> Decimal(1).exp()
Decimal('2.718281828459045235360287471')
>>> Decimal(321).exp()
Decimal('2.561702493119680037517373933E+139')
classmethod from_float(f)

Alternativ konstruktör som endast accepterar instanser av float eller int.

Observera att Decimal.from_float(0.1) inte är detsamma som Decimal('0.1'). Eftersom 0,1 inte är exakt representerbart i binär flyttal lagras värdet som det närmaste representerbara värdet som är 0x1.999999999999ap-4. Det motsvarande värdet i decimal är 0.1000000000000000055511151231257827021181583404541015625.

Anteckning

Från Python 3.2 och framåt kan en Decimal-instans också konstrueras direkt från en float.

>>> 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')

Tillagd i version 3.1.

classmethod from_number(number)

Alternativ konstruktör som endast accepterar instanser av float, int eller Decimal, men inte strängar eller tupler.

>>> Decimal.from_number(314)
Decimal('314')
>>> Decimal.from_number(0.1)
Decimal('0.1000000000000000055511151231257827021181583404541015625')
>>> Decimal.from_number(Decimal('3.14'))
Decimal('3.14')

Tillagd i version 3.14.

fma(other, third, context=None)

Fusionerad multiplicera-add. Returnera self*other+third utan avrundning av mellanprodukten self*other.

>>> Decimal(2).fma(3, 5)
Decimal('11')
is_canonical()

Returnerar True om argumentet är kanoniskt och False annars. För närvarande är en Decimal-instans alltid kanonisk, så denna operation returnerar alltid True.

is_finite()

Returnerar True om argumentet är ett ändligt tal, och False om argumentet är oändligt eller NaN.

is_infinite()

Returnerar True om argumentet är antingen positiv eller negativ oändlighet och False annars.

is_nan()

Returnerar True om argumentet är en (tyst eller signalerande) NaN och False annars.

is_normal(context=None)

Returnerar True om argumentet är ett normalt ändligt tal. Returnerar False om argumentet är noll, subnormalt, oändligt eller ett NaN.

is_qnan()

Returnerar True om argumentet är ett tyst NaN, och False i annat fall.

is_signed()

Returnerar True om argumentet har ett negativt tecken och False annars. Observera att både nollor och NaNs kan ha tecken.

is_snan()

Returnerar True om argumentet är en NaN-signal och False annars.

is_subnormal(context=None)

Returnerar True om argumentet är subnormal, och False annars.

is_zero()

Returnerar True om argumentet är en (positiv eller negativ) nolla och False annars.

ln(context=None)

Returnerar den naturliga (bas e) logaritmen av operanden. Resultatet avrundas korrekt med hjälp av avrundningsläget ROUND_HALF_EVEN.

log10(context=None)

Returnerar bas tio logaritmen av operanden. Resultatet är korrekt avrundat med ROUND_HALF_EVEN avrundningsläge.

logb(context=None)

För ett tal som inte är noll, returneras den justerade exponenten för operanden som en Decimal-instans. Om operanden är en nolla returneras Decimal('-Infinity') och flaggan DivisionByZero` aktiveras. Om operanden är en oändlighet returneras Decimal('Infinity').

logical_and(other, context=None)

logical_and() är en logisk operation som tar två logiska operander (se Logiska operander). Resultatet är det siffervisa och av de två operanderna.

logical_invert(context=None)

logical_invert() är en logisk operation. Resultatet är den siffermässiga inverteringen av operanden.

logical_or(other, context=None)

logical_or() är en logisk operation som tar två logiska operander (se Logiska operander). Resultatet är det siffervisa eller av de två operanderna.

logical_xor(other, context=None)

logical_xor() är en logisk operation som tar två logiska operander (se Logiska operander). Resultatet är det siffermässigt uteslutande eller av de två operanderna.

max(other, context=None)

Som max(self, other) förutom att kontextens avrundningsregel tillämpas innan den returneras och att NaN-värden antingen signaleras eller ignoreras (beroende på kontexten och om de är signalerande eller tysta).

max_mag(other, context=None)

Påminner om metoden max(), men jämförelsen görs med hjälp av operandernas absoluta värden.

min(other, context=None)

Som min(self, other) förutom att kontextens avrundningsregel tillämpas innan den returneras och att NaN-värden antingen signaleras eller ignoreras (beroende på kontexten och om de är signalerande eller tysta).

min_mag(other, context=None)

Påminner om metoden min(), men jämförelsen görs med hjälp av operandernas absoluta värden.

next_minus(context=None)

Returnerar det största tal som kan representeras i den givna kontexten (eller i den aktuella trådens kontext om ingen kontext anges) som är mindre än den givna operanden.

next_plus(context=None)

Returnerar det minsta tal som kan representeras i den givna kontexten (eller i den aktuella trådens kontext om ingen kontext anges) som är större än den givna operanden.

next_toward(other, context=None)

Om de två operanderna är olika, returneras det tal som ligger närmast den första operanden i riktning mot den andra operanden. Om båda operanderna är numeriskt lika, returneras en kopia av den första operanden med tecknet satt till samma som tecknet för den andra operanden.

normalize(context=None)

Används för att producera kanoniska värden för en ekvivalensklass inom antingen den aktuella kontexten eller den angivna kontexten.

Detta har samma semantik som den unära plusoperationen, förutom att om slutresultatet är ändligt reduceras det till sin enklaste form, med alla efterföljande nollor borttagna och dess tecken bevarat. Det vill säga, om koefficienten inte är noll och är en multipel av tio divideras koefficienten med tio och exponenten ökas med 1. I annat fall (koefficienten är noll) sätts exponenten till 0. I samtliga fall är tecknet oförändrat.

Till exempel normaliseras Decimal('32.100') och Decimal('0.321000e+2') båda till det likvärdiga värdet Decimal('32.1').

Observera att avrundning görs innan reducering till enklaste form.

I de senaste versionerna av specifikationen kallas denna operation även för ”reducera”.

number_class(context=None)

Returnerar en sträng som beskriver operandens klass. Det returnerade värdet är en av följande tio strängar.

  • "-Infinity", vilket indikerar att operanden är negativ oändlighet.

  • "-Normal", vilket indikerar att operanden är ett negativt normaltal.

  • "-Subnormal", vilket indikerar att operanden är negativ och subnormal.

  • "-Zero", vilket indikerar att operanden är en negativ nolla.

  • "+Zero", vilket indikerar att operanden är en positiv nolla.

  • "+Subnormal", vilket indikerar att operanden är positiv och subnormal.

  • "+Normal", vilket indikerar att operanden är ett positivt normalt tal.

  • "+Infinity", vilket indikerar att operanden är positiv oändlighet.

  • "NaN", vilket indikerar att operanden är ett tyst NaN (Not a Number).

  • "sNaN", vilket indikerar att operanden är en NaN-signal.

quantize(exp, rounding=None, context=None)

Returnerar ett värde som är lika med den första operanden efter avrundning och med den andra operandens exponent.

>>> Decimal('1.41421356').quantize(Decimal('1.000'))
Decimal('1.414')

Till skillnad från andra operationer, om koefficientens längd efter kvantiseringsoperationen skulle vara större än precisionen, så signaleras en InvalidOperation. Detta garanterar att den kvantiserade exponenten alltid är lika med den högra operandens exponent, såvida inte ett feltillstånd föreligger.

Till skillnad från andra operationer signalerar quantize aldrig underflöde, även om resultatet är onormalt och inexakt.

Om exponenten i den andra operanden är större än i den första kan avrundning vara nödvändig. I detta fall bestäms avrundningssättet av argumentet rounding om det ges, annars av det givna argumentet context; om inget av argumenten ges används avrundningssättet för den aktuella trådens kontext.

Ett fel returneras när den resulterande exponenten är större än Emax eller mindre än Etiny().

radix()

Returnerar Decimal(10), den radix (bas) i vilken Decimal-klassen gör all sin aritmetik. Inkluderad för kompatibilitet med specifikationen.

remainder_near(other, context=None)

Returnerar resten från att dividera self med other. Detta skiljer sig från self % other genom att tecknet på återstoden väljs så att dess absoluta värde minimeras. Mer exakt är returvärdet self - n * other där n är det heltal som ligger närmast det exakta värdet av self / other, och om två heltal ligger lika nära väljs det jämna.

Om resultatet är noll kommer dess tecken att vara tecknet för själv.

>>> 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)

Returnerar resultatet av att rotera siffrorna i den första operanden med en mängd som anges av den andra operanden. Det andra operandet måste vara ett heltal i intervallet -precision till precision. Det andra operandets absoluta värde anger antalet platser som ska roteras. Om det andra operandvärdet är positivt sker rotationen åt vänster, annars åt höger. Koefficienten i det första operandet fylls vid behov på vänster sida med nollor för att förlänga precisionen. Tecknet och exponenten för den första operanden är oförändrade.

same_quantum(other, context=None)

Testa om self och other har samma exponent eller om båda är NaN.

Denna operation påverkas inte av kontexten och är tyst: inga flaggor ändras och ingen avrundning utförs. Som ett undantag kan C-versionen ge upphov till InvalidOperation om den andra operanden inte kan konverteras exakt.

scaleb(other, context=None)

Returnerar den första operanden med exponenten justerad med den andra. På motsvarande sätt returneras den första operanden multiplicerad med 10**annan. Den andra operanden måste vara ett heltal.

shift(other, context=None)

Returnerar resultatet av att flytta siffrorna i den första operanden med ett belopp som anges av den andra operanden. Det andra operandet måste vara ett heltal i intervallet -precision till precision. Det andra operandets absoluta värde anger antalet platser som ska skiftas. Om det andra operandet är positivt sker förskjutningen åt vänster, annars åt höger. Siffror som flyttas in i koefficienten är nollor. Tecknet och exponenten för den första operanden är oförändrade.

sqrt(context=None)

Returnera kvadratroten av argumentet till full precision.

to_eng_string(context=None)

Konvertera till en sträng, med hjälp av ingenjörsnotation om en exponent behövs.

Teknisk notation har en exponent som är en multipel av 3. Detta kan ge upp till 3 siffror till vänster om decimaltecknet och kan kräva tillägg av antingen en eller två efterföljande nollor.

Detta konverterar till exempel Decimal('123E+1') till Decimal('1.23E+3').

to_integral(rounding=None, context=None)

Identisk med metoden to_integral_value(). Namnet to_integral har behållits för kompatibilitet med äldre versioner.

to_integral_exact(rounding=None, context=None)

Avrunda till närmaste heltal, signalera Inexact eller Rounded som lämpligt om avrundning sker. Avrundningsläget bestäms av parametern rounding om den är angiven, annars av den angivna contexten. Om ingen av parametrarna anges används avrundningsläget för den aktuella kontexten.

to_integral_value(rounding=None, context=None)

Avrunda till närmaste heltal utan att signalera Inexact eller Rounded. Om den anges, tillämpas avrundning; annars används avrundningsmetoden i antingen den medföljande kontexten eller den aktuella kontexten.

Decimaltal kan avrundas med hjälp av funktionen round():

round(number)
round(number, ndigits)

Om ndigits inte anges eller None, returneras det närmaste int till number, med avrundning till jämnt och utan hänsyn till avrundningssättet i Decimal-kontexten. Utlöser OverflowError om number är en oändlighet eller ValueError om det är ett (tyst eller signalerande) NaN.

Om ndigits är en int, respekteras kontextens avrundningsläge och en Decimal som representerar tal avrundat till närmaste multipel av Decimal('1E-ndigits') returneras; i detta fall är round(number, ndigits) ekvivalent med self.quantize(Decimal('1E-ndigits')). Returnerar Decimal('NaN') om tal är ett tyst NaN. Utlöser InvalidOperation om tal är ett oändligt tal, ett signalerande NaN eller om koefficientens längd efter kvantiseringsoperationen skulle vara större än det aktuella sammanhangets precision. Med andra ord, för de fall som inte är hörnfall:

  • om ndigits är positiv, returnera number avrundat till ndigits decimaler;

  • om ndigits är noll, returnera number avrundat till närmaste heltal;

  • om ndigits är negativt, returnera number avrundat till närmaste multipel av 10**abs(ndigits).

Till exempel:

>>> 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')

Logiska operander

Metoderna logical_and(), logical_invert(), logical_or() och logical_xor() förväntar sig att deras argument är logiska operander. En logisk operand är en Decimal-instans vars exponent och tecken båda är noll, och vars siffror alla är antingen 0 eller 1.

Objekt i kontext

Kontexter är miljöer för aritmetiska operationer. De styr precisionen, sätter regler för avrundning, bestämmer vilka signaler som ska behandlas som undantag och begränsar intervallet för exponenter.

Varje tråd har sin egen aktuella kontext som kan nås eller ändras med hjälp av funktionerna getcontext() och setcontext():

decimal.getcontext()

Returnerar det aktuella sammanhanget för den aktiva tråden.

decimal.setcontext(c)

Ställ in det aktuella sammanhanget för den aktiva tråden till c.

Du kan också använda with-satsen och localcontext()-funktionen för att tillfälligt ändra den aktiva kontexten.

decimal.localcontext(ctx=None, **kwargs)

Returnerar en kontexthanterare som sätter den aktuella kontexten för den aktiva tråden till en kopia av ctx vid ingången till with-satsen och återställer den tidigare kontexten när with-satsen avslutas. Om ingen kontext anges används en kopia av den aktuella kontexten. Argumentet kwargs används för att ställa in attributen för den nya kontexten.

Följande kod ställer t.ex. in den aktuella decimalprecisionen till 42 enheter, utför en beräkning och återställer sedan automatiskt det tidigare sammanhanget:

från decimal import localcontext

med localcontext() som ctx:
    ctx.prec = 42 # Utför en beräkning med hög precision
    s = beräkna_något()
s = +s # Runda tillbaka slutresultatet till standardprecisionen

Med hjälp av nyckelordsargument skulle koden vara följande:

från decimal import localcontext

med localcontext(prec=42) som ctx:
    s = beräkna_något()
s = +s

Utlöser TypeError om kwargs anger ett attribut som Context inte stöder. Utlöser antingen TypeError eller ValueError om kwargs anger ett ogiltigt värde för ett attribut.

Ändrad i version 3.11: localcontext() stöder nu inställning av kontextattribut genom användning av nyckelordsargument.

decimal.IEEEContext(bits)

Returnerar ett kontextobjekt som initierats till rätt värden för ett av IEEE:s utbytesformat. Argumentet måste vara en multipel av 32 och mindre än IEEE_CONTEXT_MAX_BITS.

Tillagd i version 3.14.

Nya kontexter kan också skapas med hjälp av Context-konstruktören som beskrivs nedan. Dessutom tillhandahåller modulen tre färdiga kontexter:

decimal.BasicContext

Detta är en standardkontext som definieras av General Decimal Arithmetic Specification. Precisionen är satt till nio. Avrundning är satt till ROUND_HALF_UP. Alla flaggor är rensade. Alla traps är aktiverade (behandlas som undantag) utom Inexact, Rounded och Subnormal.

Eftersom många av fällorna är aktiverade är detta sammanhang användbart för felsökning.

decimal.ExtendedContext

Detta är en standardkontext som definieras av General Decimal Arithmetic Specification. Precisionen är satt till nio. Avrundning är satt till ROUND_HALF_EVEN. Alla flaggor är rensade. Inga fällor är aktiverade (så att undantag inte uppstår under beräkningar).

Eftersom fällorna är inaktiverade är detta sammanhang användbart för applikationer som föredrar att ha resultatvärdet NaN eller Infinity istället för att skapa undantag. Detta gör att en applikation kan slutföra en körning trots förhållanden som annars skulle stoppa programmet.

decimal.DefaultContext

Denna kontext används av Context-konstruktören som en prototyp för nya kontexter. Om man ändrar ett fält (t.ex. precision) ändras standardvärdet för nya kontexter som skapas av konstruktören Context.

Detta sammanhang är mest användbart i flertrådade miljöer. Om du ändrar ett av fälten innan trådarna har startats innebär det att du ställer in systemomfattande standardvärden. Det är inte rekommenderat att ändra fälten efter att trådarna har startat eftersom det kräver trådsynkronisering för att förhindra tävlingsförhållanden.

I enkeltrådade miljöer är det att föredra att inte använda detta sammanhang alls. Skapa istället kontexter explicit enligt beskrivningen nedan.

Standardvärdena är Context.prec=``28``, Context.rounding=ROUND_HALF_EVEN, och aktiverade fällor för Overflow, InvalidOperation, och DivisionByZero.

Förutom de tre medföljande kontexterna kan nya kontexter skapas med Context-konstruktören.

class decimal.Context(prec=None, rounding=None, Emin=None, Emax=None, capitals=None, clamp=None, flags=None, traps=None)

Skapar en ny kontext. Om ett fält inte anges eller är None, kopieras standardvärdena från DefaultContext. Om fältet flags inte anges eller är None, rensas alla flaggor.

prec

Ett heltal i intervallet [1, MAX_PREC`] som anger precisionen för aritmetiska operationer i kontexten.

rounding

En av de konstanter som anges i avsnittet Rounding Modes.

traps
flags

Listor över eventuella signaler som ska ställas in. I allmänhet bör nya kontexter endast ställa in fällor och lämna flaggorna fria.

Emin
Emax

Heltal som anger de yttre gränser som tillåts för exponenter. Emin måste ligga i intervallet [MIN_EMIN, 0], Emax i intervallet [0, MAX_EMAX].

capitals

Antingen 0 eller 1 (standard). Om värdet är satt till 1 skrivs exponenter ut med ett stort E; annars används ett litet e: Decimal('6.02e+23').

clamp

Antingen 0 (standard) eller 1. Om den är satt till 1, är exponenten e för en Decimal-instans som kan representeras i detta sammanhang strikt begränsad till intervallet Emin - prec + 1 <= e <= Emax - prec + 1. Om clamp är 0 gäller ett svagare villkor: den justerade exponenten för Decimal-instansen är högst Emax. När clamp är 1 kommer ett stort normalt tal, där så är möjligt, att få sin exponent reducerad och ett motsvarande antal nollor tillagda till sin koefficient, för att passa exponentbegränsningarna; detta bevarar talets värde men förlorar information om signifikanta efterföljande nollor. Till exempel:

>>> Context(prec=6, Emax=999, clamp=1).create_decimal('1.23e999')
Decimal('1.23000E+999')

Ett clamp-värde på 1 ger kompatibilitet med de decimala utbytesformat med fast bredd som anges i IEEE 754.

Klassen Context definierar flera metoder för allmänna ändamål samt ett stort antal metoder för att utföra aritmetik direkt i ett givet sammanhang. Dessutom finns det för var och en av de Decimal-metoder som beskrivs ovan (med undantag för metoderna adjusted() och as_tuple()) en motsvarande Context-metod. Till exempel, för en Context-instans C och Decimal-instans x, är C.exp(x) ekvivalent med x.exp(context=C). Varje Context-metod accepterar ett Python-heltal (en instans av int) överallt där en Decimal-instans accepteras.

clear_flags()

Återställer alla flaggor till 0.

clear_traps()

Återställer alla fällor till 0.

Tillagd i version 3.3.

copy()

Returnerar en kopia av kontexten.

copy_decimal(num)

Returnerar en kopia av Decimal-instansen num.

create_decimal(num)

Skapar en ny Decimal-instans från num men använder self som kontext. Till skillnad från Decimal-konstruktören tillämpas kontextens precision, avrundningsmetod, flaggor och fällor på konverteringen.

Detta är användbart eftersom konstanter ofta ges med större precision än vad som behövs i programmet. En annan fördel är att avrundning omedelbart eliminerar oavsiktliga effekter från siffror som ligger utanför den aktuella precisionen. I följande exempel innebär oavrundade indata att resultatet kan ändras om man lägger till noll i en summa:

>>> getcontext().prec = 3
>>> Decimal('3.4445') + Decimal('1.0023')
Decimal('4.45')
>>> Decimal('3.4445') + Decimal(0) + Decimal('1.0023')
Decimal('4.44')

Denna metod implementerar IBM-specifikationens ”to-number”-operation. Om argumentet är en sträng tillåts inga inledande eller avslutande blanksteg eller understrykningstecken.

create_decimal_from_float(f)

Skapar en ny Decimal-instans från en float f men avrundning med self som kontext. Till skillnad från klassmetoden Decimal.from_float() tillämpas kontextens precision, avrundningsmetod, flaggor och fällor på konverteringen.

>>> 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

Tillagd i version 3.1.

Etiny()

Returnerar ett värde lika med Emin - prec + 1, vilket är det lägsta exponentvärdet för subnormala resultat. När underflöde inträffar sätts exponenten till Etiny.

Etop()

Returnerar ett värde som är lika med Emax - prec + 1.

Det vanliga sättet att arbeta med decimaler är att skapa Decimal-instanser och sedan tillämpa aritmetiska operationer som äger rum inom den aktuella kontexten för den aktiva tråden. Ett alternativt tillvägagångssätt är att använda kontextmetoder för att beräkna inom en specifik kontext. Metoderna liknar dem för klassen Decimal och beskrivs bara kortfattat här.

abs(x)

Returnerar det absoluta värdet av x.

add(x, y)

Returnera summan av x och y.

canonical(x)

Returnerar samma Decimal-objekt x.

compare(x, y)

Jämför x och y numeriskt.

compare_signal(x, y)

Jämför värdena för de två operanderna numeriskt.

compare_total(x, y)

Jämför två operander med hjälp av deras abstrakta representation.

compare_total_mag(x, y)

Jämför två operander med hjälp av deras abstrakta representation, utan att ta hänsyn till tecken.

copy_abs(x)

Returnerar en kopia av x med tecknet satt till 0.

copy_negate(x)

Returnerar en kopia av x med inverterat tecken.

copy_sign(x, y)

Kopierar tecknet från y till x.

divide(x, y)

Returnera x dividerat med y.

divide_int(x, y)

Returnerar x dividerat med y, trunkerat till ett heltal.

divmod(x, y)

Dividerar två tal och returnerar heltalsdelen av resultatet.

exp(x)

Returnerar e ** x.

fma(x, y, z)

Returnerar x multiplicerat med y, plus z.

is_canonical(x)

Returnerar True om x är kanonisk; annars returneras False.

is_finite(x)

Returnerar True om x är ändlig; annars returneras False.

is_infinite(x)

Returnerar True om x är oändlig; annars returneras False.

is_nan(x)

Returnerar True om x är en qNaN eller sNaN; annars returneras False.

is_normal(x)

Returnerar True om x är ett normalt tal; annars returneras False.

is_qnan(x)

Returnerar True om x är ett tyst NaN; annars returneras False.

is_signed(x)

Returnerar True om x är negativ; annars returneras False.

is_snan(x)

Returnerar True om x är en signalerande NaN; annars returneras False.

is_subnormal(x)

Returnerar True om x är subnormal; annars returneras False.

is_zero(x)

Returnerar True om x är en nolla; annars returneras False.

ln(x)

Returnerar den naturliga (bas e) logaritmen för x.

log10(x)

Returnerar bas 10-logaritmen för x.

logb(x)

Returnerar exponenten av magnituden för operandens MSD.

logical_and(x, y)

Använder den logiska operationen och mellan varje operands siffror.

logical_invert(x)

Invertera alla siffrorna i x.

logical_or(x, y)

Tillämpar den logiska operationen eller mellan varje operands siffror.

logical_xor(x, y)

Tillämpar den logiska operationen xor mellan varje operands siffror.

max(x, y)

Jämför två värden numeriskt och returnerar det högsta värdet.

max_mag(x, y)

Jämför värdena numeriskt utan att ta hänsyn till deras tecken.

min(x, y)

Jämför två värden numeriskt och returnerar det lägsta värdet.

min_mag(x, y)

Jämför värdena numeriskt utan att ta hänsyn till deras tecken.

minus(x)

Minus motsvarar den unära prefixoperatorn minus i Python.

multiply(x, y)

Returnera produkten av x och y.

next_minus(x)

Returnerar det största representerbara talet som är mindre än x.

next_plus(x)

Returnerar det minsta representerbara talet som är större än x.

next_toward(x, y)

Returnerar det tal som ligger närmast x, i riktning mot y.

normalize(x)

Reducerar x till sin enklaste form.

number_class(x)

Returnerar en indikation på klassen för x.

plus(x)

Plus motsvarar den unära prefixoperatorn plus i Python. Denna operation tillämpar kontextens precision och avrundning, så det är inte en identitetsoperation.

power(x, y, modulo=None)

Returnerar x till potensen av y, reducerad modulo modulo om den anges.

Beräkna x**y med två argument. Om x är negativt måste y vara heltal. Resultatet blir inexakt om inte y är heltal och resultatet är ändligt och kan uttryckas exakt i ’precisionssiffror’. Kontextens avrundningsläge används. Resultat avrundas alltid korrekt i Python-versionen.

Decimal(0) ** Decimal(0) resulterar i InvalidOperation, och om InvalidOperation inte fångas, resulterar det i Decimal('NaN').

Ändrad i version 3.3: C-modulen beräknar power() i termer av de korrekt avrundade funktionerna exp() och ln(). Resultatet är väldefinierat men bara ”nästan alltid korrekt avrundat”.

Med tre argument beräkna (x**y) % modulo. För formen med tre argument gäller följande restriktioner för argumenten:

  • alla tre argumenten måste vara integrerade

  • y måste vara icke-negativ

  • minst en av x eller y måste vara icke-noll

  • modulo måste vara icke-noll och ha högst ’precision’ siffror

Det värde som erhålls genom Context.power(x, y, modulo) är lika med det värde som skulle erhållas genom att beräkna (x**y) % modulo med obegränsad precision, men beräknas mer effektivt. Resultatets exponent är noll, oavsett exponenterna för x, y och modulo. Resultatet är alltid exakt.

quantize(x, y)

Returnerar ett värde som är lika med x (avrundat), med exponenten y.

radix()

Returnerar bara 10, eftersom detta är decimal, :)

remainder(x, y)

Returnerar restvärdet från heltalsdivision.

Om resultatet inte är noll har det samma tecken som den ursprungliga utdelningen.

remainder_near(x, y)

Returnerar x - y * n, där n är det heltal som ligger närmast det exakta värdet av x / y (om resultatet är 0 kommer dess tecken att vara tecknet för x).

rotate(x, y)

Returnerar en roterad kopia av x, y gånger.

same_quantum(x, y)

Returnerar True om de två operanderna har samma exponent.

scaleb(x, y)

Returnerar den första operanden efter att ha adderat det andra värdet dess exp.

shift(x, y)

Returnerar en förskjuten kopia av x, y gånger.

sqrt(x)

Kvadratrot av ett icke-negativt tal med kontextprecision.

subtract(x, y)

Returnera skillnaden mellan x och y.

to_eng_string(x)

Konvertera till en sträng, med hjälp av ingenjörsnotation om en exponent behövs.

Teknisk notation har en exponent som är en multipel av 3. Detta kan ge upp till 3 siffror till vänster om decimaltecknet och kan kräva tillägg av antingen en eller två efterföljande nollor.

to_integral_exact(x)

Avrundas till ett heltal.

to_sci_string(x)

Konverterar ett tal till en sträng med vetenskaplig notation.

Konstanter

Konstanterna i detta avsnitt är endast relevanta för C-modulen. De ingår också i den rena Python-versionen för kompatibilitet.

32-bitars

64-bitars

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

Värdet är True. Föråldrad, eftersom Python nu alltid har trådar.

Föråldrad sedan version 3.9.

decimal.HAVE_CONTEXTVAR

Standardvärdet är True. Om Python är konfigurerad med alternativet --without-decimal-contextvar, använder C-versionen en trådlokal snarare än en koroutinlokal kontext och värdet är False. Detta är något snabbare i vissa scenarier med nästlade kontexter.

Tillagd i version 3.8.3.

Avrundningslägen

decimal.ROUND_CEILING

Runda mot Infinity.

decimal.ROUND_DOWN

Runda mot noll.

decimal.ROUND_FLOOR

Runda mot Infinity.

decimal.ROUND_HALF_DOWN

Avrunda till närmaste med oavgjorda tal mot noll.

decimal.ROUND_HALF_EVEN

Avrunda till närmaste med oavgjort till närmaste jämna heltal.

decimal.ROUND_HALF_UP

Avrunda till närmaste med tiotal som går bort från noll.

decimal.ROUND_UP

Avrunda bort från noll.

decimal.ROUND_05UP

Avrunda bort från noll om sista siffran efter avrundning mot noll skulle ha varit 0 eller 5; annars avrunda mot noll.

Signaler

Signalerna representerar förhållanden som uppstår under beräkningen. Var och en motsvarar en kontextflagga och en kontextfälla.

Kontextflaggan sätts närhelst villkoret uppfylls. Efter beräkningen kan flaggorna kontrolleras i informationssyfte (t.ex. för att avgöra om en beräkning var exakt). När du har kontrollerat flaggorna måste du rensa alla flaggor innan du startar nästa beräkning.

Om kontextens trap enabler är inställd för signalen, orsakar villkoret att ett Python-undantag utlöses. Till exempel, om DivisionByZero-fällan är inställd, kommer ett DivisionByZero-undantag att utlösas när villkoret påträffas.

class decimal.Clamped

Ändrade en exponent för att passa representationsbegränsningar.

Vanligtvis sker fastspänning när en exponent faller utanför kontextens gränser Emin och Emax. Om möjligt reduceras exponenten så att den passar genom att nollor läggs till i koefficienten.

class decimal.DecimalException

Basklass för andra signaler och en underklass till ArithmeticError.

class decimal.DivisionByZero

Signalerar division av ett icke oändligt tal med noll.

Kan uppstå vid division, modulo-division eller när ett tal upphöjs till en negativ potens. Om denna signal inte fångas upp returneras Infinity eller -Infinity med det tecken som bestäms av ingångarna till beräkningen.

class decimal.Inexact

Indikerar att avrundning har skett och att resultatet inte är exakt.

Signalerar när siffror som inte är noll har tagits bort under avrundningen. Det avrundade resultatet returneras. Signalflaggan eller trap används för att upptäcka när resultaten är inexakta.

class decimal.InvalidOperation

En ogiltig operation utfördes.

Indikerar att en åtgärd begärdes som inte är meningsfull. Om den inte fångas upp returneras NaN. Möjliga orsaker inkluderar:

Oändlighet - Oändlighet
0 * Infinity
Oändlighet / Oändlighet
x % 0
Oändligt % x
sqrt(-x) och x > 0
0 ** 0
x ** (icke heltal)
x ** oändlighet
class decimal.Overflow

Numeriskt överflöde.

Anger att exponenten är större än Context.Emax efter att avrundning har skett. Om den inte fångas beror resultatet på avrundningsläget, antingen dras det inåt till det största representativa ändliga talet eller avrundas utåt till Infinity. I båda fallen signaleras också Inexact och Rounded.

class decimal.Rounded

Avrundning skedde, men möjligen gick ingen information förlorad.

Signaleras när avrundning tar bort siffror, även om dessa siffror är noll (t.ex. avrundning av 5,00 till 5,0). Om den inte fångas, returneras resultatet oförändrat. Denna signal används för att upptäcka förlust av signifikanta siffror.

class decimal.Subnormal

Exponent var lägre än Emin före avrundning.

Inträffar när ett operationsresultat är onormalt (exponenten är för liten). Om det inte fångas, returneras resultatet oförändrat.

class decimal.Underflow

Numeriskt underflöde med resultatet avrundat till noll.

Inträffar när ett subnormalt resultat pressas till noll genom avrundning. Inexact och Subnormal signaleras också.

class decimal.FloatOperation

Möjliggör striktare semantik för blandning av floats och decimaler.

Om signalen inte är fångad (standard) är det tillåtet att blanda floats och decimaler i Decimal-konstruktorn, create_decimal() och alla jämförelseoperatorer. Både konvertering och jämförelser är exakta. Varje förekomst av en blandad operation registreras tyst genom att ställa in FloatOperation i kontextflaggorna. Explicita konverteringar med from_float() eller create_decimal_from_float() sätter inte flaggan.

I annat fall (signalen fångas upp) är endast jämlikhetsjämförelser och explicita konverteringar tysta. Alla andra blandade operationer ger upphov till FloatOperation.

Följande tabell sammanfattar signalernas hierarki:

exceptions.ArithmeticError(exceptions.Exception)
    DecimalException
        Klämd
        DivisionByZero(DecimalException, exceptions.ZeroDivisionError)
        Inexakt
            Överflöde(Inexakt, Avrundad)
            Underflow(Inexact, Rounded, Subnormal)
        OgiltigOperation
        Avrundad
        Subnormal
        FloatOperation(DecimalException, undantag.TypeError)

Flyttalsnoteringar

Minska avrundningsfel med ökad precision

Användningen av decimalt flyttal eliminerar fel i decimalrepresentationen (vilket gör det möjligt att representera 0.1 exakt); vissa operationer kan dock fortfarande medföra avrundningsfel när siffror som inte är noll överstiger den fasta precisionen.

Effekterna av avrundningsfel kan förstärkas genom addition eller subtraktion av nästan motsatta mängder, vilket leder till förlust av signifikans. Knuth ger två instruktiva exempel där avrundad aritmetik med flyttal med otillräcklig precision leder till att de associativa och distributiva egenskaperna hos addition bryts ned:

# 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')

Modulen decimal gör det möjligt att återställa identiteterna genom att utöka precisionen tillräckligt för att undvika förlust av signifikans:

>>> 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')

Särskilda värden

Talsystemet för modulen decimal innehåller specialvärden som NaN, NaN, Infinity, Infinity och två nollor, +0 och -0.

Oändligheter kan konstrueras direkt med: Decimal('Infinity'). De kan också uppstå genom att dividera med noll när signalen DivisionByZero inte är spärrad. På samma sätt kan oändlighet uppstå när man avrundar bortom gränserna för det största representerbara talet när signalen Overflow inte fångas upp.

De oändliga talen är signerade (affina) och kan användas i aritmetiska operationer där de behandlas som mycket stora, obestämda tal. Om man t.ex. adderar en konstant till oändligheten får man ett annat oändligt resultat.

Vissa operationer är obestämda och returnerar NaN, eller om InvalidOperation-signalen fångas, ger upphov till ett undantag. Till exempel, 0/0 returnerar NaN vilket betyder ”inte ett tal”. Denna variant av NaN är tyst och när den väl har skapats kommer den att flöda genom andra beräkningar som alltid resulterar i en annan NaN. Detta beteende kan vara användbart för en serie beräkningar som ibland saknar indata — det gör att beräkningen kan fortsätta medan specifika resultat flaggas som ogiltiga.

En variant är NaN som signalerar istället för att vara tyst efter varje operation. Detta är ett användbart returvärde när ett ogiltigt resultat måste avbryta en beräkning för särskild hantering.

Beteendet hos Pythons jämförelseoperatorer kan vara lite förvånande när en NaN är inblandad. Ett test för likhet där en av operanderna är en tyst eller signalerande NaN returnerar alltid False` (även när man gör Decimal('NaN')==Decimal('NaN')), medan ett test för olikhet alltid returnerar True`. Ett försök att jämföra två decimaler med någon av operatorerna <, <=, > eller >= kommer att ge upphov till signalen InvalidOperation om någon av operanderna är ett NaN, och returnera False om denna signal inte fångas upp. Observera att General Decimal Arithmetic-specifikationen inte specificerar beteendet för direkta jämförelser; dessa regler för jämförelser som involverar ett NaN har hämtats från IEEE 854-standarden (se tabell 3 i avsnitt 5.7). För att säkerställa strikt standardöverensstämmelse, använd metoderna compare() och compare_signal() istället.

De signerade nollorna kan uppstå vid beräkningar som underflödar. De behåller det tecken som skulle ha blivit resultatet om beräkningen hade utförts med större precision. Eftersom deras magnitud är noll behandlas både positiva och negativa nollor som lika och deras tecken är informativt.

Förutom de två signerade nollorna, som är olika men ändå lika, finns det olika representationer av noll med olika noggrannhet men ändå likvärdiga i värde. Detta tar lite tid att vänja sig vid. För ett öga som är vant vid normaliserade flyttalsrepresentationer är det inte omedelbart uppenbart att följande beräkning ger ett värde som är lika med noll:

>>> 1 / Decimal('Infinity')
Decimal('0E-1000026')

Arbeta med trådar

Funktionen getcontext() ger åtkomst till ett olika Context-objekt för varje tråd. Att ha separata trådkontexter innebär att trådar kan göra ändringar (t.ex. getcontext().prec=10) utan att störa andra trådar.

På samma sätt tilldelar funktionen setcontext() automatiskt sitt mål till den aktuella tråden.

Om setcontext() inte har anropats före getcontext(), kommer getcontext() automatiskt att skapa en ny kontext för användning i den aktuella tråden. Nya kontextobjekt har standardvärden från decimal.DefaultContext-objektet.

Flaggan sys.flags.thread_inherit_context påverkar kontexten för nya trådar. Om flaggan är false kommer nya trådar att starta med en tom kontext. I detta fall kommer getcontext() att skapa ett nytt kontextobjekt när den anropas och använda standardvärdena från DefaultContext. Om flaggan är true kommer nya trådar att starta med en kopia av kontexten från den som anropar threading.Thread.start().

För att styra standardvärdena så att varje tråd använder samma värden i hela applikationen, modifierar du DefaultContext-objektet direkt. Detta bör göras innan några trådar startas så att det inte blir ett race condition mellan trådar som anropar getcontext(). Till exempel:

# Ställ in applikationsomfattande standardvärden för alla trådar som ska startas
DefaultContext.prec = 12
DefaultContext.avrundning = ROUND_DOWN
DefaultContext.traps = ExtendedContext.traps.copy()
DefaultContext.traps[InvalidOperation] = 1
setcontext(DefaultContext)

# Efteråt kan trådarna startas
t1.start()
t2.start()
t3.start()
 . . .

Recept

Här är några recept som fungerar som verktygsfunktioner och som visar hur man kan arbeta med klassen Decimal:

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

Decimal FAQ

Q. Det är besvärligt att skriva decimal.Decimal('1234.5'). Finns det något sätt att minimera skrivandet när man använder den interaktiva tolken?

A. Vissa användare förkortar konstruktören till bara en enda bokstav:

>>> D = decimal.Decimal
>>> D('1.23') + D('3.45')
Decimal('4.68')

Q. I en fastpunktsapplikation med två decimaler har vissa indata många decimaler och måste avrundas. Andra ska inte ha överflödiga siffror och måste valideras. Vilka metoder bör användas?

A. Metoden quantize() avrundar till ett fast antal decimaler. Om Inexact-fällan är inställd är den också användbar för validering:

>>> 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

Q. När jag väl har giltiga tvåplatsinmatningar, hur behåller jag den invariansen genom en applikation?

A. Vissa operationer, som addition, subtraktion och multiplikation med ett heltal, bevarar automatiskt fixpunkten. Andra operationer, t.ex. division och multiplikation med annat än heltal, ändrar antalet decimaler och måste följas upp med ett quantize()-steg:

>>> 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')

Vid utveckling av fastpunktstillämpningar är det praktiskt att definiera funktioner för att hantera quantize()-steget:

>>> 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')

Q. Det finns många sätt att uttrycka samma värde. Siffrorna 200, 200.000, 2E2 och .02E+4 har alla samma värde med olika noggrannhet. Finns det något sätt att omvandla dem till ett enda igenkännbart kanoniskt värde?

A. Metoden normalize() mappar alla likvärdiga värden till en enda representant:

>>> 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')]

Q. När sker avrundning i en beräkning?

A. Det sker efter beräkningen. Filosofin bakom decimalspecifikationen är att tal betraktas som exakta och skapas oberoende av det aktuella sammanhanget. De kan till och med ha större precision än det aktuella sammanhanget. Beräkningar utförs med dessa exakta indata och sedan tillämpas avrundning (eller andra kontextoperationer) på resultatet av beräkningen:

>>> 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')

Q. Vissa decimalvärden skrivs alltid ut med exponentiell notation. Finns det något sätt att få en icke-exponentiell representation?

A. För vissa värden är exponentiell notation det enda sättet att uttrycka antalet signifikanta ställen i koefficienten. Om man t.ex. uttrycker 5,0E+3 som 5000 hålls värdet konstant, men man kan inte visa originalets signifikans på två ställen.

Om en applikation inte bryr sig om att spåra signifikans är det enkelt att ta bort exponenten och de efterföljande nollorna, vilket gör att signifikansen försvinner men värdet förblir oförändrat:

>>> def remove_exponent(d):
...     return d.quantize(Decimal(1)) if d == d.to_integral() else d.normalize()
>>> remove_exponent(Decimal('5E+3'))
Decimal('5000')

Q. Finns det något sätt att konvertera en vanlig float till en Decimal?

A. Ja, alla binära flyttal kan uttryckas exakt som decimaltal, även om en exakt konvertering kan kräva mer precision än intuitionen skulle föreslå:

>>> Decimal(math.pi)
Decimal('3.141592653589793115997963468544185161590576171875')

Q. Hur kan jag i en komplex beräkning försäkra mig om att jag inte har fått ett felaktigt resultat på grund av otillräcklig precision eller avrundningsavvikelser?

A. Decimalmodulen gör det enkelt att testa resultat. En bra metod är att köra om beräkningarna med större precision och med olika avrundningslägen. Om resultaten skiljer sig mycket åt tyder det på otillräcklig precision, problem med avrundningslägen, dåligt konditionerade indata eller en numeriskt instabil algoritm.

Q. Jag har märkt att kontextprecision tillämpas på resultatet av operationer men inte på indata. Finns det något att se upp med när man blandar värden med olika precisioner?

A. Ja, det stämmer. Principen är att alla värden anses vara exakta och det gäller även aritmetiken för dessa värden. Endast resultaten avrundas. Fördelen med inmatningar är att ”det du skriver är det du får”. En nackdel är att resultaten kan se konstiga ut om man glömmer att indata inte har avrundats:

>>> getcontext().prec = 3
>>> Decimal('3.104') + Decimal('2.104')
Decimal('5.21')
>>> Decimal('3.104') + Decimal('0.000') + Decimal('2.104')
Decimal('5.20')

Lösningen är antingen att öka precisionen eller att tvinga fram avrundning av indata med hjälp av den unära plusoperationen:

>>> getcontext().prec = 3
>>> +Decimal('1.23456789')      # unary plus triggers rounding
Decimal('1.23')

Alternativt kan indata avrundas vid skapandet med hjälp av metoden Context.create_decimal():

>>> Context(prec=5, rounding=ROUND_DOWN).create_decimal('1.2345678')
Decimal('1.2345')

Q. Är CPython-implementeringen snabb för stora tal?

A. Ja, det stämmer. I CPython- och PyPy3-implementeringarna integrerar C/CFFI-versionerna av decimalmodulen höghastighetsbiblioteket libmpdec för aritmetik med flytande punkter med godtycklig precision och korrekt avrundad decimal [1]. libmpdec använder Karatsuba-multiplikation för medelstora tal och Number Theoretic Transform för mycket stora tal.

Kontexten måste anpassas för aritmetik med exakt godtycklig precision. Emin och Emax bör alltid sättas till maximala värden, clamp bör alltid vara 0 (standard). Att ställa in prec kräver viss försiktighet.

Den enklaste metoden för att prova bignum-aritmetik är att använda det maximala värdet för prec samt [2]:

>>> setcontext(Context(prec=MAX_PREC, Emax=MAX_EMAX, Emin=MIN_EMIN))
>>> x = Decimal(2) ** 256
>>> x / 128
Decimal('904625697166532776746648320380374280103671755200316906558262375061821325312')

För inexakta resultat är MAX_PREC alldeles för stor på 64-bitars plattformar och det tillgängliga minnet kommer inte att räcka till:

>>> Decimal(1) / 3
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
MemoryError

På system med overallokering (t.ex. Linux) är en mer sofistikerad metod att justera prec till mängden tillgängligt RAM-minne. Anta att du har 8 GB RAM och förväntar dig 10 samtidiga operander som använder maximalt 500 MB vardera:

>>> 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'>]

I allmänhet (och i synnerhet i system utan overallokering) rekommenderas att man uppskattar ännu snävare gränser och ställer in Inexact-fällan om alla beräkningar förväntas vara exakta.