This page describes the standard numeric and math-related functions and data types in Python 3, and how to use them.
The numbers module defines an abstract hierarchy of numeric types. The math and cmath modules contain various mathematical functions for floating-point and complex numbers. The decimal module supports exact representations of decimal numbers, using arbitrary precision arithmetic.
Numbers — numeric abstract base classes
The numbers module (PEP 3141) defines a hierarchy of numeric abstract base classes which progressively define more operations. None of the types defined in this module can be instantiated.
- Numbers: abstract numeric classes
- Math: mathematical functions
- Cmath: complex numbers
- Decimal: fixed and floating point math
- Fractions: rational numbers
- Random: pseudorandom numbers
- Statistics: mathematical statistics
- Python Overview
- Linux commands help
The “numeric tower”
Notes for type implementors
Implementors should be careful to make equal numbers equal and hash them to the same values. This may be subtle if there are two different extensions of the real numbers. For example, fractions.Fraction implements hash() as follows:
def hash(self): if self.denominator == 1: # Get integers right. return hash(self.numerator) # Expensive check, but definitely correct. if self == float(self): return hash(float(self)) else: # Use tuple’s hash to avoid a high collision rate on # simple fractions. return hash((self.numerator, self.denominator)
Adding more numeric ABCs
There are, of course, more possible ABCs for numbers, and this would be a poor hierarchy if it precluded the possibility of adding those. You can add MyFoo between Complex and Real with:
class MyFoo(Complex): … MyFoo.register(Real)
Implementing the arithmetic operations
We want to implement the arithmetic operations so that mixed-mode operations either call an implementation whose author knew about the types of both arguments, or convert both to the nearest built-in type and do the operation there. For subtypes of Integral, this means that add() and radd() should be defined as:
class MyIntegral(Integral): def add(self, other): if isinstance(other, MyIntegral): return do_my_adding_stuff(self, other) elif isinstance(other, OtherTypeIKnowAbout): return do_my_other_adding_stuff(self, other) else: return NotImplemented def radd(self, other): if isinstance(other, MyIntegral): return do_my_adding_stuff(other, self) elif isinstance(other, OtherTypeIKnowAbout): return do_my_other_adding_stuff(other, self) elif isinstance(other, Integral): return int(other) + int(self) elif isinstance(other, Real): return float(other) + float(self) elif isinstance(other, Complex): return complex(other) + complex(self) else: return NotImplemented
There are 5 different cases for a mixed-type operation on subclasses of Complex. We’ll refer to all of the above code that doesn’t refer to MyIntegral and OtherTypeIKnowAbout as “boilerplate”. a will be an instance of A, which is a subtype of Complex (a : A <: Complex), and b : B <: Complex. Consider a + b:
- If A defines an add() which accepts b, all is well.
- If A falls back to the boilerplate code, and it were to return a value from add(), we’d miss the possibility that B defines a more intelligent radd(), so the boilerplate should return NotImplemented from add(). (Or A may not implement add() at all.)
- Then B’s radd() gets a chance. If it accepts A, all is well.
- If it falls back to the boilerplate, there are no more possible methods to try, so this is where the default implementation should live.
- If B <: A, Python tries B.radd before A.add. This is ok, because it was implemented with knowledge of A, so it can handle those instances before delegating to Complex.
If A <: Complex and B <: Real without sharing any other knowledge, then the appropriate shared operation is the one involving the built-in complex, and both radd() s land there, so a+b == b+a.
Because most of the operations on any given type will be very similar, it can be useful to define a helper function which generates the forward and reverse instances of any given operator. For example, fractions.Fraction uses:
def _operator_fallbacks(monomorphic_operator, fallback_operator): def forward(a, b): if isinstance(b, (int, Fraction)): return monomorphic_operator(a, b) elif isinstance(b, float): return fallback_operator(float(a), b) elif isinstance(b, complex): return fallback_operator(complex(a), b) else: return NotImplemented forward.name = ‘’ + fallback_operator.name + ‘’ forward.doc = monomorphic_operator.doc def reverse(b, a): if isinstance(a, Rational): # Includes ints. return monomorphic_operator(a, b) elif isinstance(a, numbers.Real): return fallback_operator(float(a), float(b)) elif isinstance(a, numbers.Complex): return fallback_operator(complex(a), complex(b)) else: return NotImplemented reverse.name = ‘r’ + fallback_operator.name + ‘’ reverse.doc = monomorphic_operator.doc return forward, reverse def _add(a, b): “““a + b””” return Fraction(a.numerator * b.denominator b.numerator * a.denominator, a.denominator * b.denominator) add, radd = _operator_fallbacks(_add, operator.add)
…
Math — mathematical functions
This module is always available. It provides access to the mathematical functions defined by the C standard.
These functions cannot be used with complex numbers; use the functions of the same name from the cmath module if you require support for complex numbers. The distinction between functions which support complex numbers and those which don’t is made since most users do not want to learn quite as much mathematics as required to understand complex numbers. Receiving an exception instead of a complex result allows earlier detection of the unexpected complex number used as a parameter, so that the programmer can determine how and why it was generated in the first place.
The following functions are provided by this module. Except when explicitly noted otherwise, all return values are floats.
Number: theoretic and representation functions
Note that frexp() and modf() have a different call/return pattern than their C equivalents: they take a single argument and return a pair of values, rather than returning their second return value through an ‘output parameter’ (there is no such thing in Python).
sum([.1, .1, .1, .1, .1, .1, .1, .1, .1, .1])0.9999999999999999»> fsum([.1, .1, .1, .1, .1, .1, .1, .1, .1, .1])1.0
For the ceil(), floor(), and modf() functions, note that all floating-point numbers of sufficiently large magnitude are exact integers. Python floats carry no more than 53 bits of precision (the same as the platform C double type), in which case any float x with abs(x) >= 2**52 necessarily has no fractional bits.
Power and logarithmic functions
Trigonometric functions
Angular conversion
Hyperbolic functions
Hyperbolic functions are analogs of trigonometric functions that are based on hyperbolas instead of circles.
from math import exp, expm1»> exp(1e-5) - 1 # gives result accurate to 11 places1.0000050000069649e-05»> expm1(1e-5) # result accurate to full precision1.0000050000166668e-05
Special functions
Constants
Cmath — mathematical functions for complex numbers
This module is always available. It provides access to mathematical functions for complex numbers. The functions in this module accept integers, floating-point numbers or complex numbers as arguments. They also accepts any Python object that has either a complex() or a float() method: these methods are used to convert the object to a complex or floating-point number, respectively, and the function is then applied to the result of the conversion.
def phi(x): ‘Cumulative distribution function for the standard normal distribution’ return (1.0 + erf(x / sqrt(2.0))) / 2.0
Conversions to and from polar coordinates
A Python complex number z is stored internally using rectangular or Cartesian coordinates. It is completely determined by its real part z.real and its imaginary part z.imag. In other words:
On platforms with hardware and system-level support for signed zeros, functions involving branch cuts are continuous on both sides of the branch cut: the sign of the zero distinguishes one side of the branch cut from the other. On platforms that do not support signed zeros the continuity is as specified below.
z == z.real + z.imag*1j
Polar coordinates give an alternative way to represent a complex number. In polar coordinates, a complex number z is defined by the modulus r and the phase angle phi. The modulus r is the distance from z to the origin, while the phase phi is the counterclockwise angle, measured in radians, from the positive x-axis to the line segment that joins the origin to z.
The following functions can convert from the native rectangular coordinates to polar coordinates and back.
Classification functions
Note that the selection of functions is similar, but not identical, to that in module math. The reason for having two modules is that some users aren’t interested in complex numbers, and perhaps don’t even know what they are. They would rather have math.sqrt(-1) raise an exception than return a complex number. Also, note that the functions defined in cmath always return a complex number, even if the answer can be expressed as a real number (in which case the complex number has an imaginary part of zero).
phase(complex(-1.0, 0.0))3.141592653589793»> phase(complex(-1.0, -0.0))-3.141592653589793
A note on branch cuts: They are curves along which the given function fails to be continuous. They are a necessary feature of many complex functions. It is assumed that if you need to compute with complex functions, you understand about branch cuts. Consult almost any (not too elementary) book on complex variables for enlightenment. For information of the proper choice of branch cuts for numerical purposes, a good reference should be the following:
Decimal — decimal fixed point and floating point arithmetic
The decimal module provides support for fast correctly-rounded decimal floating point arithmetic. It offers several advantages over the float datatype:
- Decimal “is based on a floating-point model which was designed with people in mind, and necessarily has a paramount guiding principle – computers must provide an arithmetic that works in the same way as the arithmetic that people learn at school.” – excerpt from the decimal arithmetic specification.
- Decimal numbers can be represented exactly. In contrast, numbers like 1.1 and 2.2 do not have exact representations in binary floating point. End users would not expect 1.1 + 2.2 to display as 3.3000000000000003 as it does with binary floating point.
- The exactness carries over into arithmetic. In decimal floating point, 0.1 + 0.1 + 0.1 - 0.3 is exactly equal to zero. In binary floating point, the result is 5.5511151231257827e-017. While near to zero, the differences prevent reliable equality testing and differences can accumulate. For this reason, decimal is preferred in accounting applications which have strict equality invariants.
- The decimal module incorporates a notion of significant places so that 1.30 + 1.20 is 2.50. The trailing zero is kept to indicate significance. This is the customary presentation for monetary applications. For multiplication, the “schoolbook” approach uses all the figures in the multiplicands. For instance, 1.3 * 1.2 gives 1.56 while 1.30 * 1.20 gives 1.5600.
- Unlike hardware based binary floating point, the decimal module has a user alterable precision (defaulting to 28 places) which can be as large as needed for a given problem: »> from decimal import *»> getcontext().prec = 6»> Decimal(1) / Decimal(7)Decimal(‘0.142857’)»> getcontext().prec = 28»> Decimal(1) / Decimal(7)Decimal(‘0.1428571428571428571428571429’)
- Both binary and decimal floating point are implemented in terms of published standards. While the built-in float type exposes only a modest portion of its capabilities, the decimal module exposes all required parts of the standard. When needed, the programmer has full control over rounding and signal handling. This includes an option to enforce exact arithmetic using exceptions to block any inexact operations.
- The decimal module was designed to support “without prejudice, both exact unrounded decimal arithmetic (sometimes called fixed-point arithmetic) and rounded floating-point arithmetic.” – excerpt from the decimal arithmetic specification.
The module design is centered around three concepts: the decimal number, the context for arithmetic, and signals.
from decimal import *»> getcontext().prec = 6»> Decimal(1) / Decimal(7)Decimal(‘0.142857’)»> getcontext().prec = 28»> Decimal(1) / Decimal(7)Decimal(‘0.1428571428571428571428571429’)
A decimal number is immutable. It has a sign, coefficient digits, and an exponent. To preserve significance, the coefficient digits do not truncate trailing zeros. Decimals also include special values such as Infinity, -Infinity, and NaN. The standard also differentiates -0 from +0.
The context for arithmetic is an environment specifying precision, rounding rules, limits on exponents, flags indicating the results of operations, and trap enablers which determine whether signals are treated as exceptions. Rounding options include ROUND_CEILING, ROUND_DOWN, ROUND_FLOOR, ROUND_HALF_DOWN, ROUND_HALF_EVEN, ROUND_HALF_UP, ROUND_UP, and ROUND_05UP.
Signals are groups of exceptional conditions arising during the course of computation. Depending on the needs of the application, signals may be ignored, considered as informational, or treated as exceptions. The signals in the decimal module are: Clamped, InvalidOperation, DivisionByZero, Inexact, Rounded, Subnormal, Overflow, Underflow and FloatOperation.
For each signal there is a flag and a trap enabler. When a signal is encountered, its flag is set to one, then, if the trap enabler is set to one, an exception is raised. Flags are sticky, so the user needs to reset them before monitoring a calculation.
Quick-start tutorial
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=-999999, Emax=999999, capitals=1, clamp=0, flags=[], traps=[Overflow, DivisionByZero, InvalidOperation]) getcontext().prec = 7 # Set a new precision
Decimal instances can be constructed from integers, strings, floats, or tuples. Construction from an integer or a float performs an exact conversion of the value of that integer or float. Decimal numbers include special values such as NaN which stands for “Not a number”, positive and negative Infinity, and -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’)
If the FloatOperation signal is trapped, accidental mixing of decimals and floats in constructors or ordering comparisons raises an exception:
c = getcontext() c.traps[FloatOperation] = True Decimal(3.14) Traceback (most recent call last): File “
”, line 1, in decimal.FloatOperation: [<class ‘decimal.FloatOperation’>] Decimal(‘3.5’) < 3.7 Traceback (most recent call last): File “ ”, line 1, in decimal.FloatOperation: [<class ‘decimal.FloatOperation’>] Decimal(‘3.5’) == 3.5 True
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’)
If the internal limits of the C version are exceeded, constructing a decimal raises InvalidOperation:
Decimal(“1e9999999999999999999”) Traceback (most recent call last): File “
”, line 1, in decimal.InvalidOperation: [<class ‘decimal.InvalidOperation’>]
Decimals interact well with much of the rest of Python. Here is a small decimal floating point flying circus:
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’)
And some mathematical functions are also available to 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’)
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=-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
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 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=-999999, Emax=999999, capitals=1, clamp=0, 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:
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
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.
Decimal objects
In addition to the standard numeric properties, decimal floating point objects also have many specialized methods:
sign ::= ‘+’ | ‘-‘digit ::= ‘0’ | ‘1’ | ‘2’ | ‘3’ | ‘4’ | ‘5’ | ‘6’ | ‘7’ | ‘8’ | ‘9’indicator ::= ’e’ | ‘E’digits ::= digit [digit]…decimal-part ::= digits ‘.’ [digits] | [’.’] digitsexponent-part ::= indicator [sign] digitsinfinity ::= ‘Infinity’ | ‘Inf’nan ::= ‘NaN’ [digits] | ‘sNaN’ [digits]numeric-value ::= decimal-part [exponent-part] | infinitynumeric-string ::= [sign] numeric-value | [sign] nan
(-7) % 41»> Decimal(-7) % Decimal(4)Decimal(’-3’)
-7 // 4-2»> Decimal(-7) // Decimal(4)Decimal(’-1’)
Logical operands
The logical_and(), logical_invert(), logical_or(), and logical_xor() methods expect their arguments to be logical operands. A logical operand is a Decimal instance whose exponent and sign are both zero, and whose digits are all either 0 or 1.
Context objects
Contexts are environments for arithmetic operations. They govern precision, set rules for rounding, determine which signals are treated as exceptions, and limit the range for exponents.
Each thread has its own current context that is accessed or changed using the getcontext() and setcontext() functions:
You can also use the with statement and the localcontext() function to temporarily change the active context.
New contexts can also be created using the Context constructor described below. Also, the module provides three pre-made contexts:
from decimal import localcontextwith 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
In addition to the three supplied contexts, new contexts can be created with the Context constructor.
The Context class defines several general purpose methods and a large number of methods for doing arithmetic directly in a context. Also, for each of the Decimal methods described above (with the exception of the adjusted() and as_tuple() methods) there is a corresponding Context method. For example, for a Context instance C and Decimal instance x, C.exp(x) is equivalent to x.exp(context=C). Each Context method accepts a Python integer (an instance of int) anywhere that a Decimal instance is accepted.
Context(prec=6, Emax=999, clamp=1).create_decimal(‘1.23e999’)Decimal(‘1.23000E+999’)
The usual approach to working with decimals is to create Decimal instances and then apply arithmetic operations which take place in the current context for the active thread. An alternative approach is to use context methods for calculating in a specific context. The methods are similar to those for the Decimal class and are only briefly recounted here.
getcontext().prec = 3»> Decimal(‘3.4445’) + Decimal(‘1.0023’)Decimal(‘4.45’)»> Decimal(‘3.4445’) + Decimal(0) + Decimal(‘1.0023’)Decimal(‘4.44’)
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
Decimal constants
The constants in this section are only relevant for the C module. They are also included in the pure Python version for compatibility.
- all three arguments must be integraly must be nonnegativeat least one of x or y must be nonzeromodulo must be nonzero and have at most ‘precision’ digits
Rounding modes
Signals
Signals represent conditions that arise during computation. Each corresponds to one context flag and one context trap enabler.
The context flag is set whenever the condition is encountered. After the computation, flags may be checked for informational purposes (for instance, to determine whether a computation was exact). After checking the flags, clear all flags before starting the next computation.
If the context’s trap enabler is set for the signal, then the condition causes a Python exception to be raised. For example, if the DivisionByZero trap is set, then a DivisionByZero exception is raised upon encountering the condition.
The hierarchy of signals is as follows:
- Infinity - Infinity0 * InfinityInfinity / Infinityx % 0Infinity % xsqrt(-x) and x > 00 ** 0x ** (non-integer)x ** Infinity
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)
Mitigating round-off error with increased precision
The use of decimal floating point eliminates decimal representation error (making it possible to represent 0.1 exactly); however, some operations can still incur round-off error when non-zero digits exceed the fixed precision.
The effects of round-off error can be amplified by the addition or subtraction of nearly offsetting quantities resulting in loss of significance. Knuth provides two instructive examples where rounded floating point arithmetic with insufficient precision causes the breakdown of the associative and distributive properties of addition:
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’) (uv) + (uw) Decimal(‘0.01’) u * (v+w) Decimal(‘0.0060000’)
The decimal module makes it possible to restore the identities by expanding the precision sufficiently to avoid loss of significance:
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’) (uv) + (uw) Decimal(‘0.0060000’) u * (v+w) Decimal(‘0.0060000’)
Special values
The number system for the decimal module provides special values including NaN, sNaN, -Infinity, Infinity, and two zeros, +0 and -0.
Infinities can be constructed directly with: Decimal(‘Infinity’). Also, they can arise from dividing by zero when the DivisionByZero signal is not trapped. Likewise, when the Overflow signal is not trapped, infinity can result from rounding beyond the limits of the largest representable number.
The infinities are signed (affine) and used in arithmetic operations where they get treated as very large, indeterminate numbers. For instance, adding a constant to infinity gives another infinite result.
Some operations are indeterminate and return NaN, or if the InvalidOperation signal is trapped, raise an exception. For example, 0/0 returns NaN which means “not a number”. This variety of NaN is quiet and, once created, will flow through other computations always resulting in another NaN. This behavior can be helpful for a series of computations that occasionally have missing inputs — it allows the calculation to proceed while flagging specific results as invalid.
A variant is sNaN which signals rather than remaining quiet after every operation. This is a useful return value when an invalid result needs to interrupt a calculation for special handling.
The behavior of Python’s comparison operators are little surprising where a NaN is involved. A test for equality where one of the operands is a quiet or signaling NaN always returns False (even when doing Decimal(‘NaN’)==Decimal(‘NaN’)), while a test for inequality always returns True. An attempt to compare two Decimals using any of the <, <=, > or >= operators will raise the InvalidOperation signal if either operand is a NaN, and return False if this signal is not trapped. Note that the General Decimal Arithmetic specification does not specify the behavior of direct comparisons; these rules for comparisons involving a NaN were taken from the IEEE 854 standard. To ensure strict standards-compliance, use the compare() and compare-signal() methods instead.
The signed zeros can result from calculations that underflow. They keep the sign that would have resulted if the calculation had been carried out to greater precision. Since their magnitude is zero, both positive and negative zeros are treated as equal and their sign is informational.
In addition to the two signed zeros that are distinct yet equal, there are various representations of zero with differing precisions yet equivalent in value. This takes a bit of getting used to. For an eye accustomed to normalized floating point representations, it is not immediately obvious that the following calculation returns a value equal to zero:
1 / Decimal(‘Infinity’) Decimal(‘0E-1000026’)
Working with threads
The getcontext() function accesses a different Context object for each thread. Having separate thread contexts means that threads may make changes (such as getcontext().prec=10) without interfering with other threads.
Likewise, the setcontext() function automatically assigns its target to the current thread.
If setcontext() has not been called before getcontext(), then getcontext() automatically creates a new context for use in the current thread.
The new context is copied from a prototype context called DefaultContext. To control the defaults so that each thread uses the same values throughout the application, directly modify the DefaultContext object. This should be done before any threads are started so that there won’t be a race condition between threads calling getcontext(). For example:
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() . . .
Recipes
Here are a few recipes that serve as utility functions and that demonstrate ways to work with the Decimal class:
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
Q. It is cumbersome to type decimal.Decimal(‘1234.5’). Is there a way to minimize typing when using the interactive interpreter?
A. Some users abbreviate the constructor to a single letter:
D = decimal.Decimal D(‘1.23’) + D(‘3.45’) Decimal(‘4.68’)
Q. In a fixed-point application with two decimal places, some inputs have many places and need to be rounded. Others are not supposed to have excess digits and need to be validated. What methods should be used?
A. The quantize() method rounds to a fixed number of decimal places. If the Inexact trap is set, it is also useful for validation:
TWOPLACES = Decimal(10) ** -2 # same as Decimal(‘0.01’)
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. Once I have valid two place inputs, how do I maintain that invariant throughout an application?
A. Some operations like addition, subtraction, and multiplication by an integer automatically preserves fixed point. Others operations, like division and non-integer multiplication, changes the number of decimal places and need to be followed-up with a quantize() step:
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’)
In developing fixed-point applications, it is convenient to define functions to handle the quantize() step:
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. There are many ways to express the same value. The numbers 200, 200.000, 2E2, and 02E+4 all have the same value at various precisions. Is there a way to transform them to a single recognizable canonical value?
A. The normalize() method maps all equivalent values to a single representative:
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. Some decimal values always print with exponential notation. Is there a way to get a non-exponential representation?
A. For some values, exponential notation is the only way to express the number of significant places in the coefficient. For example, expressing 5.0E+3 as 5000 keeps the value constant but cannot show the original’s two-place significance.
If an application does not care about tracking significance, it is easy to remove the exponent and trailing zeroes, losing significance, but keeping the value unchanged:
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. Is there a way to convert a regular float to a Decimal?
A. Yes, any binary floating point number can be exactly expressed as a Decimal though an exact conversion may take more precision than intuition would suggest:
Decimal(math.pi) Decimal(‘3.141592653589793115997963468544185161590576171875’)
Q. Within a complex calculation, how can I make sure that I haven’t gotten a spurious result because of insufficient precision or rounding anomalies.
A. The decimal module makes it easy to test results. A best practice is to re-run calculations using greater precision and with various rounding modes. Widely differing results indicate insufficient precision, rounding mode issues, ill-conditioned inputs, or a numerically unstable algorithm.
Q. I noticed that context precision is applied to the results of operations but not to the inputs. Is there anything to watch out for when mixing values of different precisions?
A. Yes. The principle is that all values are considered to be exact and so is the arithmetic on those values. Only the results are rounded. The advantage for inputs is that “what you type is what you get”. A disadvantage is that the results can look odd if you forget that the inputs haven’t been rounded:
getcontext().prec = 3 Decimal(‘3.104’) + Decimal(‘2.104’) Decimal(‘5.21’) Decimal(‘3.104’) + Decimal(‘0.000’) + Decimal(‘2.104’) Decimal(‘5.20’)
The solution is either to increase precision or force rounding of inputs using the unary plus operation:
getcontext().prec = 3 +Decimal(‘1.23456789’) # unary plus triggers rounding Decimal(‘1.23’)
Alternatively, inputs can be rounded upon creation using the Context.create_decimal() method:
Context(prec=5, rounding=ROUND_DOWN).create_decimal(‘1.2345678’) Decimal(‘1.2345’)
Fractions — rational numbers
The Fraction class inherits from the abstract base class numbers.Rational, and implements all of the methods and operations from that class. Fraction instances are hashable, and should be treated as immutable. Also, Fraction has the following properties and methods:
[sign] numerator [’/’ denominator]
from fractions import Fraction»> Fraction(16, -10)Fraction(-8, 5)»> Fraction(123)Fraction(123, 1)»> Fraction()Fraction(0, 1)»> Fraction(‘3/7’)Fraction(3, 7)»> Fraction(’ -3/7 ‘)Fraction(-3, 7)»> Fraction(‘1.414213 \t\n’)Fraction(1414213, 1000000)»> Fraction(’-.125’)Fraction(-1, 8)»> Fraction(‘7e-6’)Fraction(7, 1000000)»> Fraction(2.25)Fraction(9, 4)»> Fraction(1.1)Fraction(2476979795053773, 2251799813685248)»> from decimal import Decimal»> Fraction(Decimal(‘1.1’))Fraction(11, 10)
Random — generate pseudorandom numbers
This module implements pseudorandom number generators for various distributions.
from fractions import Fraction»> Fraction(‘3.1415926535897932’).limit_denominator(1000)Fraction(355, 113)
from math import pi, cos»> Fraction(cos(pi/3))Fraction(4503599627370497, 9007199254740992)»> Fraction(cos(pi/3)).limit_denominator()Fraction(1, 2)»> Fraction(1.1).limit_denominator()Fraction(11, 10)
from math import floor»> floor(Fraction(355, 113))3
For integers, there is uniform selection from a range. For sequences, there is uniform selection of a random element, a function to generate a random permutation of a list in-place, and a function for random sampling without replacement.
On the real line, there are functions to compute uniform, normal (Gaussian), lognormal, negative exponential, gamma, and beta distributions. For generating distributions of angles, the von Mises distribution is available.
Almost all module functions depend on the basic function random(), which generates a random float uniformly in the semi-open range [0.0, 1.0). Python uses the Mersenne Twister as the core generator. It produces 53-bit precision floats and has a period of 2**19937-1. The underlying implementation in C is both fast and threadsafe. The Mersenne Twister is one of the most extensively tested random number generators in existence. However, being completely deterministic, it is not suitable for all purposes, and is completely unsuitable for cryptographic purposes.
The functions supplied by this module are actually bound methods of a hidden instance of the random.Random class. You can instantiate instances of Random to get generators that don’t share state.
Class Random can also be subclassed if you want to use a different basic generator, in that case, override the random(), seed(), getstate(), and setstate() methods. Optionally, a new generator can supply a getrandbits() method — this allows randrange() to produce selections over an arbitrarily large range.
The random module also provides the SystemRandom class which uses the system function os.urandom() to generate random numbers from sources provided by the operating system.
Bookkeeping functions:
The pseudorandom generators of this module should not be used for security purposes. Use os.urandom() or SystemRandom if you require a cryptographically secure pseudorandom number generator.
Functions for integers:
Functions for sequences:
The following functions generate specific real-valued distributions. Function parameters are named after the corresponding variables in the distribution’s equation, as used in common mathematical practice; most of these equations is in any statistics text.
Alternative Generator:
x ** (alpha - 1) * math.exp(-x / beta)pdf(x) = ────────────────────────────────────── math.gamma(alpha) * beta ** alpha
Notes on reproducibility
Sometimes it is useful to be able to reproduce the sequences given by a pseudo random number generator. By re-using a seed value, the same sequence should be reproducible from run to run as long as multiple threads are not running.
Most of the random module’s algorithms and seeding functions are subject to change across Python versions, but two aspects are guaranteed not to change:
- If a new seeding method is added, then a backward compatible seeder will be offered.
- The generator’s random() method continues to produce the same sequence when the compatible seeder is given the same seed.
Examples and recipes
Basic usage:
random.random() # Random float x, 0.0 <= x < 1.0 0.37444887175646646 random.uniform(1, 10) # Random float x, 1.0 <= x < 10.0 1.1800146073117523 random.randrange(10) # Integer from 0 to 9 7 random.randrange(0, 101, 2) # Even integer from 0 to 100 26 random.choice(‘abcdefghij’) # Single random element ‘c’ items = [1, 2, 3, 4, 5, 6, 7] random.shuffle(items) items [7, 3, 2, 5, 6, 4, 1] random.sample([1, 2, 3, 4, 5], 3) # Three samples without replacement [4, 1, 5]
A common task is to make a random.choice() with weighted probabilities.
If the weights are small integer ratios, a simple technique is to build a sample population with repeats:
weighted_choices = [(‘Red’, 3), (‘Blue’, 2), (‘Yellow’, 1), (‘Green’, 4)] population = [val for val, cnt in weighted_choices for i in range(cnt)] random.choice(population) ‘Green’
A more general approach is to arrange the weights in a cumulative distribution with itertools.accumulate(), and then locate the random value with bisect.bisect():
choices, weights = zip(*weighted_choices) cumdist = list(itertools.accumulate(weights)) x = random.random() * cumdist[-1] choices[bisect.bisect(cumdist, x)] ‘Blue’
Statistics — mathematical statistics functions
This module provides functions for calculating mathematical statistics of numeric (Real-valued) data.
Statistics functions
Math exceptions
A single exception is defined by the math module:
Unless explicitly noted otherwise, these functions support int, float, decimal.Decimal and fractions.Fraction. Behaviour with other types (whether in the numeric tower or not) is currently unsupported. Mixed types are also undefined and implementation-dependent. If your input data consists of mixed types, you can use map() to ensure a consistent result, e.g., map(float, input_data).
mean([1, 2, 3, 4, 4])2.8»> mean([-1.0, 2.5, 3.25, 5.75])2.625»> from fractions import Fraction as F»> mean([F(3, 7), F(1, 21), F(5, 3), F(1, 3)])Fraction(13, 21)»> from decimal import Decimal as D»> mean([D(“0.5”), D(“0.75”), D(“0.625”), D(“0.375”)])Decimal(‘0.5625’)
median([1, 3, 5])3
median([1, 3, 5, 7])4.0
median_low([1, 3, 5])3»> median_low([1, 3, 5, 7])3
median_high([1, 3, 5])3»> median_high([1, 3, 5, 7])5
median_grouped([52, 52, 53, 54])52.5
median_grouped([1, 2, 2, 3, 4, 4, 4, 4, 4, 5])3.7
median_grouped([1, 3, 3, 5, 7], interval=1)3.25»> median_grouped([1, 3, 3, 5, 7], interval=2)3.5
mode([1, 1, 2, 3, 3, 3, 3, 4])3
mode([“red”, “blue”, “blue”, “red”, “green”, “red”, “red”])‘red’
pstdev([1.5, 2.5, 2.5, 2.75, 3.25, 4.75])0.986893273527251
data = [0.0, 0.25, 0.25, 1.25, 1.5, 1.75, 2.75, 3.25]»> pvariance(data)1.25
mu = mean(data)»> pvariance(data, mu)1.25
from decimal import Decimal as D»> pvariance([D(“27.5”), D(“30.25”), D(“30.25”), D(“34.5”), D(“41.75”)])Decimal(‘24.815’)»> from fractions import Fraction as F»> pvariance([F(1, 4), F(5, 4), F(1, 2)])Fraction(13, 72)
stdev([1.5, 2.5, 2.5, 2.75, 3.25, 4.75])1.0810874155219827
data = [2.75, 1.75, 1.25, 0.25, 0.5, 1.25, 3.5]»> variance(data)1.3720238095238095
m = mean(data)»> variance(data, m)1.3720238095238095
from decimal import Decimal as D»> variance([D(“27.5”), D(“30.25”), D(“30.25”), D(“34.5”), D(“41.75”)])Decimal(‘31.01875’)»> from fractions import Fraction as F»> variance([F(1, 6), F(1, 2), F(5, 3)])Fraction(67, 108)