mirror of
https://github.com/python/cpython.git
synced 2025-08-04 00:48:58 +00:00
Add a notes section to the docs:
* Discuss representation error versus loss of significance. * Document special values including qNaN, sNaN, +0, -0. * Show the suprising display of non-normalized zero values.
This commit is contained in:
parent
5c8d29cb13
commit
2864b808c7
1 changed files with 97 additions and 1 deletions
|
@ -828,6 +828,102 @@ The following table summarizes the hierarchy of signals:
|
|||
\end{verbatim}
|
||||
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
\subsection{Floating Point Notes \label{decimal-notes}}
|
||||
|
||||
The use of decimal floating point eliminates decimal representation error
|
||||
(making it possible to represent \constant{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 break down of the associative and
|
||||
distributive properties of addition:
|
||||
|
||||
\begin{verbatim}
|
||||
# Examples from Seminumerical Algorithms, Section 4.2.2.
|
||||
>>> from decimal import *
|
||||
>>> 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")
|
||||
\end{verbatim}
|
||||
|
||||
The \module{decimal} module makes it possible to restore the identities
|
||||
by expanding the precision sufficiently to avoid loss of significance:
|
||||
|
||||
\begin{verbatim}
|
||||
>>> 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")
|
||||
\end{verbatim}
|
||||
|
||||
|
||||
The number system for the \module{decimal} module provides special
|
||||
values including \constant{NaN}, \constant{sNaN}, \constant{-Infinity},
|
||||
\constant{Infinity}, and two zeroes, \constant{+0} and \constant{-0}.
|
||||
|
||||
Infinities can constructed directly with: \code{Decimal('Infinity')}. Also,
|
||||
they can arise from dividing by zero when the \exception{DivisionByZero}
|
||||
signal is not trapped. Likewise, when the \exception{Overflow} signal is not
|
||||
trapped, infinity can result from rounding beyond the limits of the largest
|
||||
representable number.
|
||||
|
||||
The infinities are signed (affine) and can be 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 \constant{NaN} or when the
|
||||
\exception{InvalidOperation} signal is trapped, raise an exception. For
|
||||
example, \code{0/0} returns \constant{NaN} which means ``not a number''. This
|
||||
variety of \constant{NaN} is quiet and, once created, will flow through other
|
||||
computations always resulting in another \constant{NaN}. This behavior can be
|
||||
useful 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 \constant{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 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, the positive and negative zero are treated as equal and their
|
||||
sign is informational.
|
||||
|
||||
In addition to the two signed zeros which 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:
|
||||
|
||||
\begin{verbatim}
|
||||
>>> 1 / Decimal('Infinity')
|
||||
Decimal("0E-1000000026")
|
||||
\end{verbatim}
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
\subsection{Working with threads \label{decimal-threads}}
|
||||
|
||||
|
@ -864,7 +960,7 @@ t2.start()
|
|||
t3.start()
|
||||
. . .
|
||||
\end{verbatim}
|
||||
|
||||
|
||||
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue