The usual start to using decimals is importing the module, viewing the current context with getcontext() and, if necessary, setting new values for precision, rounding, or enabled traps:
>>> from decimal import * >>> getcontext() Context(prec=28, rounding=ROUND_HALF_EVEN, Emin=-999999999, Emax=999999999, capitals=1, flags=[], traps=[Overflow, InvalidOperation, DivisionByZero]) >>> getcontext().prec = 7 # Set a new precision
Decimal instances can be constructed from integers, strings, or tuples. To create a Decimal from a float, first convert it to a string. This serves as an explicit reminder of the details of the conversion (including representation error). Decimal numbers include special values such as NaN which stands for ``Not a number'', positive and negative Infinity, and -0.
>>> Decimal(10) Decimal("10") >>> Decimal("3.14") Decimal("3.14") >>> Decimal((0, (3, 1, 4), -2)) Decimal("3.14") >>> Decimal(str(2.0 ** 0.5)) Decimal("1.41421356237") >>> Decimal("NaN") Decimal("NaN") >>> Decimal("-Infinity") Decimal("-Infinity")
The significance of a new Decimal is determined solely by the number of digits input. Context precision and rounding only come into play during arithmetic operations.
>>> 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")
Decimals interact well with much of the rest of Python. Here is a small decimal floating point flying circus:
>>> data = 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.3400000000000001 >>> round(a, 1) # round() first converts to binary floating point 1.3 >>> int(a) 1 >>> a * 5 Decimal("6.70") >>> a * b Decimal("2.5058") >>> c % a Decimal("0.77")
The quantize() method rounds a number to a fixed exponent. This method is useful for monetary applications that often round results to a fixed number of places:
>>> Decimal('7.325').quantize(Decimal('.01'), rounding=ROUND_DOWN) Decimal("7.32") >>> Decimal('7.325').quantize(Decimal('1.'), rounding=ROUND_UP) Decimal("8")
As shown above, the getcontext() function accesses the current context and allows the settings to be changed. This approach meets the needs of most applications.
For more advanced work, it may be useful to create alternate contexts using the Context() constructor. To make an alternate active, use the setcontext() function.
In accordance with the standard, the Decimal module provides two ready to use standard contexts, BasicContext and ExtendedContext. The former is especially useful for debugging because many of the traps are enabled:
>>> 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=-999999999, Emax=999999999, capitals=1, 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
Contexts also have signal flags for monitoring exceptional conditions encountered during computations. The flags remain set until explicitly cleared, so it is best to clear the flags before each set of monitored computations by using the clear_flags() method.
>>> setcontext(ExtendedContext) >>> getcontext().clear_flags() >>> Decimal(355) / Decimal(113) Decimal("3.14159292") >>> getcontext() Context(prec=9, rounding=ROUND_HALF_EVEN, Emin=-999999999, Emax=999999999, capitals=1, flags=[Inexact, Rounded], traps=[])
The flags entry shows that the rational approximation to Pi was rounded (digits beyond the context precision were thrown away) and that the result is inexact (some of the discarded digits were non-zero).
Individual traps are set using the dictionary in the traps field of a context:
>>> 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
Most programs adjust the current context only once, at the beginning of the program. And, in many applications, data is converted to Decimal with a single cast inside a loop. With context set and decimals created, the bulk of the program manipulates the data no differently than with other Python numeric types.
See About this document... for information on suggesting changes.