The decimal module provides support for decimal floating point arithmetic.
-
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") [precision is applied after
# an operation, e.g. addition]
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) # 1.3 - round() first converts to binary floating point
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")
-
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=[])
-
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 "", line 1, in -toplevel-
Decimal(1) / Decimal(0)
DivisionByZero: x / 0
-
adjusted( ) - Return the adjusted exponent after shifting out the coefficient's rightmost digits until only the lead digit remains: Decimal("321e+5").adjusted() returns seven. Used for determining the position of the most significant digit with respect to the decimal point.
-
as_tuple( ) - Returns a tuple representation of the number: "(sign, digittuple, exponent)".
Decimal('2525.75').as_tuple() # (0, (2, 5, 2, 5, 7, 5), -2)
-
compare( other[, context]) - Compares like __cmp__() but returns a decimal instance:
a or b is a NaN # Decimal("NaN")
a < b # Decimal("-1")
a == b # Decimal("0")
a > b # Decimal("1")
-
normalize( [context]) - Normalize the number by stripping the rightmost trailing zeroes and converting any result equal to Decimal("0") to Decimal("0e0"). Used for producing canonical values for members of an equivalence class.
Decimal("32.100").normalize() # Decimal("32.1")
Decimal("0.32100e+2").normalize() # Decimal("32.1")
-
quantize( exp [, rounding[, context[, watchexp]]]) - Quantize makes the exponent the same as exp. Searches for a rounding method in rounding, then in context, and then in the current context.
If watchexp is set (default), then an error is returned whenever the resulting exponent is greater than Emax or less than Etiny.
-
remainder_near( other[, context]) - Computes the modulo as either a positive or negative value depending on which is closest to zero. For instance, "Decimal(10).remainder_near(6)" returns Decimal("-2") which is closer to zero than Decimal("4").
If both are equally close, the one chosen will have the same sign as self.
Decimal(10).remainder_near(6) # Decimal("-2")
-
same_quantum( other[, context]) - Test whether self and other have the same exponent or whether both are NaN.
Decimal('10').same_quantum(Decimal('20')) # True
Decimal('10').same_quantum(Decimal('200')) # True
Decimal('10').same_quantum(Decimal('20.1')) # False
-
sqrt( [context]) - Return the square root to full precision.
Decimal(25).sqrt() # Decimal("5")
Decimal(26).sqrt() # Decimal("5.099019513592784830028224109")
-
to_eng_string( [context]) - Convert to an engineering-type string.
Engineering notation has an exponent which is a multiple of 3, so there are up to 3 digits left of the decimal place.
Decimal("123E+1").to_eng_string() # Decimal("1.23E+3")
-
to_integral( [rounding[, context]]) - Rounds to the nearest integer without signaling Inexact or Rounded. If given, applies rounding; otherwise, uses the rounding method in either the supplied context or the current context.
Decimal('5.25').to_integral() # Decimal("5")
Decimal('5.75').to_integral() # Decimal("6")
index
