python-peps/pep-0327/index.html

1360 lines
99 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="color-scheme" content="light dark">
<title>PEP 327 Decimal Data Type | peps.python.org</title>
<link rel="shortcut icon" href="../_static/py.png">
<link rel="canonical" href="https://peps.python.org/pep-0327/">
<link rel="stylesheet" href="../_static/style.css" type="text/css">
<link rel="stylesheet" href="../_static/mq.css" type="text/css">
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" media="(prefers-color-scheme: light)" id="pyg-light">
<link rel="stylesheet" href="../_static/pygments_dark.css" type="text/css" media="(prefers-color-scheme: dark)" id="pyg-dark">
<link rel="alternate" type="application/rss+xml" title="Latest PEPs" href="https://peps.python.org/peps.rss">
<meta property="og:title" content='PEP 327 Decimal Data Type | peps.python.org'>
<meta property="og:description" content="The idea is to have a Decimal data type, for every use where decimals are needed but binary floating point is too inexact.">
<meta property="og:type" content="website">
<meta property="og:url" content="https://peps.python.org/pep-0327/">
<meta property="og:site_name" content="Python Enhancement Proposals (PEPs)">
<meta property="og:image" content="https://peps.python.org/_static/og-image.png">
<meta property="og:image:alt" content="Python PEPs">
<meta property="og:image:width" content="200">
<meta property="og:image:height" content="200">
<meta name="description" content="The idea is to have a Decimal data type, for every use where decimals are needed but binary floating point is too inexact.">
<meta name="theme-color" content="#3776ab">
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<symbol id="svg-sun-half" viewBox="0 0 24 24" pointer-events="all">
<title>Following system colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="9"></circle>
<path d="M12 3v18m0-12l4.65-4.65M12 14.3l7.37-7.37M12 19.6l8.85-8.85"></path>
</svg>
</symbol>
<symbol id="svg-moon" viewBox="0 0 24 24" pointer-events="all">
<title>Selected dark colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z"></path>
</svg>
</symbol>
<symbol id="svg-sun" viewBox="0 0 24 24" pointer-events="all">
<title>Selected light colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
</symbol>
</svg>
<script>
document.documentElement.dataset.colour_scheme = localStorage.getItem("colour_scheme") || "auto"
</script>
<section id="pep-page-section">
<header>
<h1>Python Enhancement Proposals</h1>
<ul class="breadcrumbs">
<li><a href="https://www.python.org/" title="The Python Programming Language">Python</a> &raquo; </li>
<li><a href="../pep-0000/">PEP Index</a> &raquo; </li>
<li>PEP 327</li>
</ul>
<button id="colour-scheme-cycler" onClick="setColourScheme(nextColourScheme())">
<svg aria-hidden="true" class="colour-scheme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-dark"><use href="#svg-moon"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-light"><use href="#svg-sun"></use></svg>
<span class="visually-hidden">Toggle light / dark / auto colour theme</span>
</button>
</header>
<article>
<section id="pep-content">
<h1 class="page-title">PEP 327 Decimal Data Type</h1>
<dl class="rfc2822 field-list simple">
<dt class="field-odd">Author<span class="colon">:</span></dt>
<dd class="field-odd">Facundo Batista &lt;facundo&#32;&#97;t&#32;taniquetil.com.ar&gt;</dd>
<dt class="field-even">Status<span class="colon">:</span></dt>
<dd class="field-even"><abbr title="Accepted and implementation complete, or no longer active">Final</abbr></dd>
<dt class="field-odd">Type<span class="colon">:</span></dt>
<dd class="field-odd"><abbr title="Normative PEP with a new feature for Python, implementation change for CPython or interoperability standard for the ecosystem">Standards Track</abbr></dd>
<dt class="field-even">Created<span class="colon">:</span></dt>
<dd class="field-even">17-Oct-2003</dd>
<dt class="field-odd">Python-Version<span class="colon">:</span></dt>
<dd class="field-odd">2.4</dd>
<dt class="field-even">Post-History<span class="colon">:</span></dt>
<dd class="field-even">30-Nov-2003, 02-Jan-2004, 29-Jan-2004</dd>
</dl>
<hr class="docutils" />
<section id="contents">
<details><summary>Table of Contents</summary><ul class="simple">
<li><a class="reference internal" href="#abstract">Abstract</a></li>
<li><a class="reference internal" href="#motivation">Motivation</a><ul>
<li><a class="reference internal" href="#the-problem-with-binary-float">The problem with binary float</a></li>
<li><a class="reference internal" href="#why-floating-point">Why floating point?</a></li>
<li><a class="reference internal" href="#why-not-rational">Why not rational?</a></li>
<li><a class="reference internal" href="#so-what-do-we-have">So, what do we have?</a></li>
</ul>
</li>
<li><a class="reference internal" href="#general-decimal-arithmetic-specification">General Decimal Arithmetic Specification</a><ul>
<li><a class="reference internal" href="#the-arithmetic-model">The Arithmetic Model</a></li>
<li><a class="reference internal" href="#numbers">Numbers</a></li>
<li><a class="reference internal" href="#context">Context</a></li>
<li><a class="reference internal" href="#default-contexts">Default Contexts</a></li>
<li><a class="reference internal" href="#exceptional-conditions">Exceptional Conditions</a></li>
<li><a class="reference internal" href="#rounding-algorithms">Rounding Algorithms</a></li>
</ul>
</li>
<li><a class="reference internal" href="#rationale">Rationale</a><ul>
<li><a class="reference internal" href="#explicit-construction">Explicit construction</a><ul>
<li><a class="reference internal" href="#from-int-or-long">From int or long</a></li>
<li><a class="reference internal" href="#from-string">From string</a></li>
<li><a class="reference internal" href="#from-float">From float</a></li>
<li><a class="reference internal" href="#from-tuples">From tuples</a></li>
<li><a class="reference internal" href="#from-decimal">From Decimal</a></li>
<li><a class="reference internal" href="#syntax-for-all-cases">Syntax for All Cases</a></li>
<li><a class="reference internal" href="#creating-from-context">Creating from Context</a></li>
</ul>
</li>
<li><a class="reference internal" href="#implicit-construction">Implicit construction</a><ul>
<li><a class="reference internal" href="#id15">From int or long</a></li>
<li><a class="reference internal" href="#id16">From string</a></li>
<li><a class="reference internal" href="#id17">From float</a></li>
<li><a class="reference internal" href="#id18">From Decimal</a></li>
</ul>
</li>
<li><a class="reference internal" href="#use-of-context">Use of Context</a></li>
<li><a class="reference internal" href="#python-usability">Python Usability</a></li>
</ul>
</li>
<li><a class="reference internal" href="#documentation">Documentation</a><ul>
<li><a class="reference internal" href="#decimal-attributes">Decimal Attributes</a></li>
<li><a class="reference internal" href="#decimal-methods">Decimal Methods</a></li>
<li><a class="reference internal" href="#context-attributes">Context Attributes</a></li>
<li><a class="reference internal" href="#context-methods">Context Methods</a></li>
</ul>
</li>
<li><a class="reference internal" href="#reference-implementation">Reference Implementation</a></li>
<li><a class="reference internal" href="#references">References</a></li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
</ul>
</details></section>
<section id="abstract">
<h2><a class="toc-backref" href="#abstract" role="doc-backlink">Abstract</a></h2>
<p>The idea is to have a Decimal data type, for every use where decimals
are needed but binary floating point is too inexact.</p>
<p>The Decimal data type will support the Python standard functions and
operations, and must comply with the decimal arithmetic ANSI standard
X3.274-1996 <a class="footnote-reference brackets" href="#id19" id="id1">[1]</a>.</p>
<p>Decimal will be floating point (as opposed to fixed point) and will
have bounded precision (the precision is the upper limit on the
number of significant digits in a result). However, precision is
user-settable, and a notion of significant trailing zeroes is supported
so that fixed-point usage is also possible.</p>
<p>This work is based on code and test functions written by Eric Price,
Aahz and Tim Peters. Just before Python 2.4a1, the decimal.py
<a class="reference internal" href="#reference-implementation">reference implementation</a> was moved into the standard library; along
with the documentation and the test suite, this was the work of
Raymond Hettinger. Much of the explanation in this PEP is taken from
Cowlishaws work <a class="footnote-reference brackets" href="#id20" id="id2">[2]</a>, comp.lang.python and python-dev.</p>
</section>
<section id="motivation">
<h2><a class="toc-backref" href="#motivation" role="doc-backlink">Motivation</a></h2>
<p>Here Ill expose the reasons of why I think a Decimal data type is
needed and why other numeric data types are not enough.</p>
<p>I wanted a Money data type, and after proposing a pre-PEP in
comp.lang.python, the community agreed to have a numeric data type
with the needed arithmetic behaviour, and then build Money over it:
all the considerations about quantity of digits after the decimal
point, rounding, etc., will be handled through Money. It is not the
purpose of this PEP to have a data type that can be used as Money
without further effort.</p>
<p>One of the biggest advantages of implementing a standard is that
someone already thought out all the creepy cases for you. And to a
standard GvR redirected me: Mike Cowlishaws General Decimal
Arithmetic specification <a class="footnote-reference brackets" href="#id20" id="id3">[2]</a>. This document defines a general
purpose decimal arithmetic. A correct implementation of this
specification will conform to the decimal arithmetic defined in
ANSI/IEEE standard 854-1987, except for some minor restrictions, and
will also provide unrounded decimal arithmetic and integer arithmetic
as proper subsets.</p>
<section id="the-problem-with-binary-float">
<h3><a class="toc-backref" href="#the-problem-with-binary-float" role="doc-backlink">The problem with binary float</a></h3>
<p>In decimal math, there are many numbers that cant be represented with
a fixed number of decimal digits, e.g. 1/3 = 0.3333333333…….</p>
<p>In base 2 (the way that standard floating point is calculated), 1/2 =
0.1, 1/4 = 0.01, 1/8 = 0.001, etc. Decimal 0.2 equals 2/10 equals
1/5, resulting in the binary fractional number
0.001100110011001… As you can see, the problem is that some decimal
numbers cant be represented exactly in binary, resulting in small
roundoff errors.</p>
<p>So we need a decimal data type that represents exactly decimal
numbers. Instead of a binary data type, we need a decimal one.</p>
</section>
<section id="why-floating-point">
<h3><a class="toc-backref" href="#why-floating-point" role="doc-backlink">Why floating point?</a></h3>
<p>So we go to decimal, but why <em>floating point</em>?</p>
<p>Floating point numbers use a fixed quantity of digits (precision) to
represent a number, working with an exponent when the number gets too
big or too small. For example, with a precision of 5:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> <span class="mi">1234</span> <span class="o">==&gt;</span> <span class="mf">1234e0</span>
<span class="mi">12345</span> <span class="o">==&gt;</span> <span class="mf">12345e0</span>
<span class="mi">123456</span> <span class="o">==&gt;</span> <span class="mf">12346e1</span>
</pre></div>
</div>
<p>(note that in the last line the number got rounded to fit in five digits).</p>
<p>In contrast, we have the example of a <code class="docutils literal notranslate"><span class="pre">long</span></code> integer with infinite
precision, meaning that you can have the number as big as you want,
and youll never lose any information.</p>
<p>In a fixed point number, the position of the decimal point is fixed.
For a fixed point data type, check Tim Peters FixedPoint at
SourceForge <a class="footnote-reference brackets" href="#id22" id="id4">[4]</a>. Ill go for floating point because its easier to
implement the arithmetic behaviour of the standard, and then you can
implement a fixed point data type over Decimal.</p>
<p>But why cant we have a floating point number with infinite precision?
Its not so easy, because of inexact divisions. E.g.: 1/3 =
0.3333333333333… ad infinitum. In this case you should store an
infinite amount of 3s, which takes too much memory, ;).</p>
<p>John Roth proposed to eliminate the division operator and force the
user to use an explicit method, just to avoid this kind of trouble.
This generated adverse reactions in comp.lang.python, as everybody
wants to have support for the <code class="docutils literal notranslate"><span class="pre">/</span></code> operator in a numeric data type.</p>
<p>With this exposed maybe youre thinking “Hey! Can we just store the 1
and the 3 as numerator and denominator?”, which takes us to the next
point.</p>
</section>
<section id="why-not-rational">
<h3><a class="toc-backref" href="#why-not-rational" role="doc-backlink">Why not rational?</a></h3>
<p>Rational numbers are stored using two integer numbers, the numerator
and the denominator. This implies that the arithmetic operations
cant be executed directly (e.g. to add two rational numbers you first
need to calculate the common denominator).</p>
<p>Quoting Alex Martelli:</p>
<blockquote>
<div>The performance implications of the fact that summing two
rationals (which take O(M) and O(N) space respectively) gives a
rational which takes O(M+N) memory space is just too troublesome.
There are excellent Rational implementations in both pure Python
and as extensions (e.g., gmpy), but theyll always be a “niche
market” IMHO. Probably worth PEPping, not worth doing without
Decimal which is the right way to represent sums of money, a
truly major use case in the real world.</div></blockquote>
<p>Anyway, if youre interested in this data type, you maybe will want to
take a look at <a class="pep reference internal" href="../pep-0239/" title="PEP 239 Adding a Rational Type to Python">PEP 239</a>: Adding a Rational Type to Python.</p>
</section>
<section id="so-what-do-we-have">
<h3><a class="toc-backref" href="#so-what-do-we-have" role="doc-backlink">So, what do we have?</a></h3>
<p>The result is a Decimal data type, with bounded precision and floating
point.</p>
<p>Will it be useful? I cant say it better than Alex Martelli:</p>
<blockquote>
<div>Python (out of the box) doesnt let you have binary floating point
numbers <em>with whatever precision you specify</em>: youre limited to
what your hardware supplies. Decimal, be it used as a fixed or
floating point number, should suffer from no such limitation:
whatever bounded precision you may specify on number creation
(your memory permitting) should work just as well. Most of the
expense of programming simplicity can be hidden from application
programs and placed in a suitable decimal arithmetic type. As per
<a class="reference external" href="http://speleotrove.com/decimal/">http://speleotrove.com/decimal/</a>, <em>a single data type can be
used for integer, fixed-point, and floating-point decimal
arithmetic</em> and for money arithmetic which doesnt drive the
application programmer crazy.</div></blockquote>
<p>There are several uses for such a data type. As I said before, I will
use it as base for Money. In this case the bounded precision is not
an issue; quoting Tim Peters:</p>
<blockquote>
<div>A precision of 20 would be way more than enough to account for
total world economic output, down to the penny, since the
beginning of time.</div></blockquote>
</section>
</section>
<section id="general-decimal-arithmetic-specification">
<h2><a class="toc-backref" href="#general-decimal-arithmetic-specification" role="doc-backlink">General Decimal Arithmetic Specification</a></h2>
<p>Here Ill include information and descriptions that are part of the
specification <a class="footnote-reference brackets" href="#id20" id="id5">[2]</a> (the structure of the number, the context, etc.).
All the requirements included in this section are not for discussion
(barring typos or other mistakes), as they are in the standard, and
the PEP is just for implementing the standard.</p>
<p>Because of copyright restrictions, I can not copy here explanations
taken from the specification, so Ill try to explain it in my own
words. I firmly encourage you to read the original specification
document <a class="footnote-reference brackets" href="#id20" id="id6">[2]</a> for details or if you have any doubt.</p>
<section id="the-arithmetic-model">
<h3><a class="toc-backref" href="#the-arithmetic-model" role="doc-backlink">The Arithmetic Model</a></h3>
<p>The specification is based on a decimal arithmetic model, as defined
by the relevant standards: IEEE 854 <a class="footnote-reference brackets" href="#id21" id="id7">[3]</a>, ANSI X3-274 <a class="footnote-reference brackets" href="#id19" id="id8">[1]</a>, and the
proposed revision <a class="footnote-reference brackets" href="#id23" id="id9">[5]</a> of IEEE 754 <a class="footnote-reference brackets" href="#id24" id="id10">[6]</a>.</p>
<p>The model has three components:</p>
<ul class="simple">
<li>Numbers: just the values that the operation uses as input or output.</li>
<li>Operations: addition, multiplication, etc.</li>
<li>Context: a set of parameters and rules that the user can select and
which govern the results of operations (for example, the precision
to be used).</li>
</ul>
</section>
<section id="numbers">
<h3><a class="toc-backref" href="#numbers" role="doc-backlink">Numbers</a></h3>
<p>Numbers may be finite or special values. The former can be
represented exactly. The latter are infinites and undefined (such as
0/0).</p>
<p>Finite numbers are defined by three parameters:</p>
<ul class="simple">
<li>Sign: 0 (positive) or 1 (negative).</li>
<li>Coefficient: a non-negative integer.</li>
<li>Exponent: a signed integer, the power of ten of the coefficient
multiplier.</li>
</ul>
<p>The numerical value of a finite number is given by:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span><span class="o">**</span><span class="n">sign</span> <span class="o">*</span> <span class="n">coefficient</span> <span class="o">*</span> <span class="mi">10</span><span class="o">**</span><span class="n">exponent</span>
</pre></div>
</div>
<p>Special values are named as following:</p>
<ul class="simple">
<li>Infinity: a value which is infinitely large. Could be positive or
negative.</li>
<li>Quiet NaN (“qNaN”): represent undefined results (<em>Not a Number</em>).
Does not cause an Invalid operation condition. The sign in a NaN
has no meaning.</li>
<li>Signaling NaN (“sNaN”): also <em>Not a Number</em>, but will cause an
Invalid operation condition if used in any operation.</li>
</ul>
</section>
<section id="context">
<h3><a class="toc-backref" href="#context" role="doc-backlink">Context</a></h3>
<p>The context is a set of parameters and rules that the user can select
and which govern the results of operations (for example, the precision
to be used).</p>
<p>The context gets that name because it surrounds the Decimal numbers,
with parts of context acting as input to, and output of, operations.
Its up to the application to work with one or several contexts,
but definitely the idea is not to get a context per Decimal number.
For example, a typical use would be to set the contexts precision to
20 digits at the start of a program, and never explicitly use context
again.</p>
<p>These definitions dont affect the internal storage of the Decimal
numbers, just the way that the arithmetic operations are performed.</p>
<p>The context is mainly defined by the following parameters (see
<a class="reference internal" href="#context-attributes">Context Attributes</a> for all context attributes):</p>
<ul class="simple">
<li>Precision: The maximum number of significant digits that can result
from an arithmetic operation (integer &gt; 0). There is no maximum for
this value.</li>
<li>Rounding: The name of the algorithm to be used when rounding is
necessary, one of “round-down”, “round-half-up”, “round-half-even”,
“round-ceiling”, “round-floor”, “round-half-down”, and “round-up”.
See <a class="reference internal" href="#rounding-algorithms">Rounding Algorithms</a> below.</li>
<li>Flags and trap-enablers: <a class="reference internal" href="#exceptional-conditions">Exceptional conditions</a> are grouped into
signals, controllable individually, each consisting of a flag
(boolean, set when the signal occurs) and a trap-enabler (a boolean
that controls behavior). The signals are: “clamped”,
“division-by-zero”, “inexact”, “invalid-operation”, “overflow”,
“rounded”, “subnormal” and “underflow”.</li>
</ul>
</section>
<section id="default-contexts">
<h3><a class="toc-backref" href="#default-contexts" role="doc-backlink">Default Contexts</a></h3>
<p>The specification defines two default contexts, which should be easily
selectable by the user.</p>
<p>Basic Default Context:</p>
<ul class="simple">
<li>flags: all set to 0</li>
<li>trap-enablers: inexact, rounded, and subnormal are set to 0; all
others are set to 1</li>
<li>precision: is set to 9</li>
<li>rounding: is set to round-half-up</li>
</ul>
<p>Extended Default Context:</p>
<ul class="simple">
<li>flags: all set to 0</li>
<li>trap-enablers: all set to 0</li>
<li>precision: is set to 9</li>
<li>rounding: is set to round-half-even</li>
</ul>
</section>
<section id="exceptional-conditions">
<h3><a class="toc-backref" href="#exceptional-conditions" role="doc-backlink">Exceptional Conditions</a></h3>
<p>The table below lists the exceptional conditions that may arise during
the arithmetic operations, the corresponding signal, and the defined
result. For details, see the specification <a class="footnote-reference brackets" href="#id20" id="id11">[2]</a>.</p>
<table class="docutils align-default">
<thead>
<tr class="row-odd"><th class="head">Condition</th>
<th class="head">Signal</th>
<th class="head">Result</th>
</tr>
</thead>
<tbody>
<tr class="row-even"><td>Clamped</td>
<td>clamped</td>
<td>see spec <a class="footnote-reference brackets" href="#id20" id="id12">[2]</a></td>
</tr>
<tr class="row-odd"><td>Division by zero</td>
<td>division-by-zero</td>
<td>[sign,inf]</td>
</tr>
<tr class="row-even"><td>Inexact</td>
<td>inexact</td>
<td>unchanged</td>
</tr>
<tr class="row-odd"><td>Invalid operation</td>
<td>invalid-operation</td>
<td>[0,qNaN] (or [s,qNaN] or [s,qNaN,d]
when the cause is a signaling NaN)</td>
</tr>
<tr class="row-even"><td>Overflow</td>
<td>overflow</td>
<td>depends on the rounding mode</td>
</tr>
<tr class="row-odd"><td>Rounded</td>
<td>rounded</td>
<td>unchanged</td>
</tr>
<tr class="row-even"><td>Subnormal</td>
<td>subnormal</td>
<td>unchanged</td>
</tr>
<tr class="row-odd"><td>Underflow</td>
<td>underflow</td>
<td>see spec <a class="footnote-reference brackets" href="#id20" id="id13">[2]</a></td>
</tr>
</tbody>
</table>
<p>Note: when the standard talks about “Insufficient storage”, as long as
this is implementation-specific behaviour about not having enough
storage to keep the internals of the number, this implementation will
raise MemoryError.</p>
<p>Regarding Overflow and Underflow, theres been a long discussion in
python-dev about artificial limits. The general consensus is to keep
the artificial limits only if there are important reasons to do that.
Tim Peters gives us three:</p>
<blockquote>
<div>…eliminating bounds on exponents effectively means overflow
(and underflow) can never happen. But overflow <em>is</em> a valuable
safety net in real life fp use, like a canary in a coal mine,
giving danger signs early when a program goes insane.<p>Virtually all implementations of 854 use (and as IBMs standard
even suggests) “forbidden” exponent values to encode non-finite
numbers (infinities and NaNs). A bounded exponent can do this at
virtually no extra storage cost. If the exponent is unbounded,
then additional bits have to be used instead. This cost remains
hidden until more time- and space- efficient implementations are
attempted.</p>
<p>Big as it is, the IBM standard is a tiny start at supplying a
complete numeric facility. Having no bound on exponent size will
enormously complicate the implementations of, e.g., decimal sin()
and cos() (theres then no a priori limit on how many digits of
pi effectively need to be known in order to perform argument
reduction).</p>
</div></blockquote>
<p>Edward Loper give us an example of when the limits are to be crossed:
probabilities.</p>
<p>That said, Robert Brewer and Andrew Lentvorski want the limits to be
easily modifiable by the users. Actually, this is quite possible:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">d1</span> <span class="o">=</span> <span class="n">Decimal</span><span class="p">(</span><span class="s2">&quot;1e999999999&quot;</span><span class="p">)</span> <span class="c1"># at the exponent limit</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">d1</span>
<span class="go">Decimal(&quot;1E+999999999&quot;)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">d1</span> <span class="o">*</span> <span class="mi">10</span> <span class="c1"># exceed the limit, got infinity</span>
<span class="gt">Traceback (most recent call last):</span>
File <span class="nb">&quot;&lt;pyshell#3&gt;&quot;</span>, line <span class="m">1</span>, in <span class="n">?</span>
<span class="w"> </span><span class="n">d1</span> <span class="o">*</span> <span class="mi">10</span>
<span class="w"> </span><span class="c">...</span>
<span class="w"> </span><span class="c">...</span>
<span class="gr">Overflow</span>: <span class="n">above Emax</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">getcontext</span><span class="p">()</span><span class="o">.</span><span class="n">Emax</span> <span class="o">=</span> <span class="mi">1000000000</span> <span class="c1"># increase the limit</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">d1</span> <span class="o">*</span> <span class="mi">10</span> <span class="c1"># does not exceed any more</span>
<span class="go">Decimal(&quot;1.0E+1000000000&quot;)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">d1</span> <span class="o">*</span> <span class="mi">100</span> <span class="c1"># exceed again</span>
<span class="gt">Traceback (most recent call last):</span>
File <span class="nb">&quot;&lt;pyshell#3&gt;&quot;</span>, line <span class="m">1</span>, in <span class="n">?</span>
<span class="w"> </span><span class="n">d1</span> <span class="o">*</span> <span class="mi">100</span>
<span class="w"> </span><span class="c">...</span>
<span class="w"> </span><span class="c">...</span>
<span class="gr">Overflow</span>: <span class="n">above Emax</span>
</pre></div>
</div>
</section>
<section id="rounding-algorithms">
<h3><a class="toc-backref" href="#rounding-algorithms" role="doc-backlink">Rounding Algorithms</a></h3>
<p><code class="docutils literal notranslate"><span class="pre">round-down</span></code>: The discarded digits are ignored; the result is
unchanged (round toward 0, truncate):</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="mf">1.123</span> <span class="o">--&gt;</span> <span class="mf">1.12</span>
<span class="mf">1.128</span> <span class="o">--&gt;</span> <span class="mf">1.12</span>
<span class="mf">1.125</span> <span class="o">--&gt;</span> <span class="mf">1.12</span>
<span class="mf">1.135</span> <span class="o">--&gt;</span> <span class="mf">1.13</span>
</pre></div>
</div>
<p><code class="docutils literal notranslate"><span class="pre">round-half-up</span></code>: If the discarded digits represent greater than or
equal to half (0.5) then the result should be incremented by 1;
otherwise the discarded digits are ignored:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="mf">1.123</span> <span class="o">--&gt;</span> <span class="mf">1.12</span>
<span class="mf">1.128</span> <span class="o">--&gt;</span> <span class="mf">1.13</span>
<span class="mf">1.125</span> <span class="o">--&gt;</span> <span class="mf">1.13</span>
<span class="mf">1.135</span> <span class="o">--&gt;</span> <span class="mf">1.14</span>
</pre></div>
</div>
<p><code class="docutils literal notranslate"><span class="pre">round-half-even</span></code>: If the discarded digits represent greater than
half (0.5) then the result coefficient is incremented by 1; if they
represent less than half, then the result is not adjusted; otherwise
the result is unaltered if its rightmost digit is even, or incremented
by 1 if its rightmost digit is odd (to make an even digit):</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="mf">1.123</span> <span class="o">--&gt;</span> <span class="mf">1.12</span>
<span class="mf">1.128</span> <span class="o">--&gt;</span> <span class="mf">1.13</span>
<span class="mf">1.125</span> <span class="o">--&gt;</span> <span class="mf">1.12</span>
<span class="mf">1.135</span> <span class="o">--&gt;</span> <span class="mf">1.14</span>
</pre></div>
</div>
<p><code class="docutils literal notranslate"><span class="pre">round-ceiling</span></code>: If all of the discarded digits are zero or if the
sign is negative the result is unchanged; otherwise, the result is
incremented by 1 (round toward positive infinity):</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> <span class="mf">1.123</span> <span class="o">--&gt;</span> <span class="mf">1.13</span>
<span class="mf">1.128</span> <span class="o">--&gt;</span> <span class="mf">1.13</span>
<span class="o">-</span><span class="mf">1.123</span> <span class="o">--&gt;</span> <span class="o">-</span><span class="mf">1.12</span>
<span class="o">-</span><span class="mf">1.128</span> <span class="o">--&gt;</span> <span class="o">-</span><span class="mf">1.12</span>
</pre></div>
</div>
<p><code class="docutils literal notranslate"><span class="pre">round-floor</span></code>: If all of the discarded digits are zero or if the
sign is positive the result is unchanged; otherwise, the absolute
value of the result is incremented by 1 (round toward negative
infinity):</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> <span class="mf">1.123</span> <span class="o">--&gt;</span> <span class="mf">1.12</span>
<span class="mf">1.128</span> <span class="o">--&gt;</span> <span class="mf">1.12</span>
<span class="o">-</span><span class="mf">1.123</span> <span class="o">--&gt;</span> <span class="o">-</span><span class="mf">1.13</span>
<span class="o">-</span><span class="mf">1.128</span> <span class="o">--&gt;</span> <span class="o">-</span><span class="mf">1.13</span>
</pre></div>
</div>
<p><code class="docutils literal notranslate"><span class="pre">round-half-down</span></code>: If the discarded digits represent greater than
half (0.5) then the result is incremented by 1; otherwise the
discarded digits are ignored:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="mf">1.123</span> <span class="o">--&gt;</span> <span class="mf">1.12</span>
<span class="mf">1.128</span> <span class="o">--&gt;</span> <span class="mf">1.13</span>
<span class="mf">1.125</span> <span class="o">--&gt;</span> <span class="mf">1.12</span>
<span class="mf">1.135</span> <span class="o">--&gt;</span> <span class="mf">1.13</span>
</pre></div>
</div>
<p><code class="docutils literal notranslate"><span class="pre">round-up</span></code>: If all of the discarded digits are zero the result is
unchanged, otherwise the result is incremented by 1 (round away from
0):</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="mf">1.123</span> <span class="o">--&gt;</span> <span class="mf">1.13</span>
<span class="mf">1.128</span> <span class="o">--&gt;</span> <span class="mf">1.13</span>
<span class="mf">1.125</span> <span class="o">--&gt;</span> <span class="mf">1.13</span>
<span class="mf">1.135</span> <span class="o">--&gt;</span> <span class="mf">1.14</span>
</pre></div>
</div>
</section>
</section>
<section id="rationale">
<h2><a class="toc-backref" href="#rationale" role="doc-backlink">Rationale</a></h2>
<p>I must separate the requirements in two sections. The first is to
comply with the ANSI standard. All the requirements for this are
specified in the Mike Cowlishaws work <a class="footnote-reference brackets" href="#id20" id="id14">[2]</a>. He also provided a
<strong>very large</strong> suite of test cases.</p>
<p>The second section of requirements (standard Python functions support,
usability, etc.) is detailed from here, where Ill include all the
decisions made and why, and all the subjects still being discussed.</p>
<section id="explicit-construction">
<h3><a class="toc-backref" href="#explicit-construction" role="doc-backlink">Explicit construction</a></h3>
<p>The explicit construction does not get affected by the context (there
is no rounding, no limits by the precision, etc.), because the context
affects just operations results. The only exception to this is when
youre <a class="reference internal" href="#creating-from-context">Creating from Context</a>.</p>
<section id="from-int-or-long">
<h4><a class="toc-backref" href="#from-int-or-long" role="doc-backlink">From int or long</a></h4>
<p>Theres no loss and no need to specify any other information:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">Decimal</span><span class="p">(</span><span class="mi">35</span><span class="p">)</span>
<span class="n">Decimal</span><span class="p">(</span><span class="o">-</span><span class="mi">124</span><span class="p">)</span>
</pre></div>
</div>
</section>
<section id="from-string">
<h4><a class="toc-backref" href="#from-string" role="doc-backlink">From string</a></h4>
<p>Strings containing Python decimal integer literals and Python float
literals will be supported. In this transformation there is no loss
of information, as the string is directly converted to Decimal (there
is not an intermediate conversion through float):</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">Decimal</span><span class="p">(</span><span class="s2">&quot;-12&quot;</span><span class="p">)</span>
<span class="n">Decimal</span><span class="p">(</span><span class="s2">&quot;23.2e-7&quot;</span><span class="p">)</span>
</pre></div>
</div>
<p>Also, you can construct in this way all special values (Infinity and
Not a Number):</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">Decimal</span><span class="p">(</span><span class="s2">&quot;Inf&quot;</span><span class="p">)</span>
<span class="n">Decimal</span><span class="p">(</span><span class="s2">&quot;NaN&quot;</span><span class="p">)</span>
</pre></div>
</div>
</section>
<section id="from-float">
<h4><a class="toc-backref" href="#from-float" role="doc-backlink">From float</a></h4>
<p>The initial discussion on this item was what should
happen when passing floating point to the constructor:</p>
<ol class="arabic simple">
<li><code class="docutils literal notranslate"><span class="pre">Decimal(1.1)</span> <span class="pre">==</span> <span class="pre">Decimal('1.1')</span></code></li>
<li><code class="docutils literal notranslate"><span class="pre">Decimal(1.1)</span> <span class="pre">==</span>
<span class="pre">Decimal('110000000000000008881784197001252...e-51')</span></code></li>
<li>an exception is raised</li>
</ol>
<p>Several people alleged that (1) is the better option here, because
its what you expect when writing <code class="docutils literal notranslate"><span class="pre">Decimal(1.1)</span></code>. And quoting John
Roth, its easy to implement:</p>
<blockquote>
<div>Its not at all difficult to find where the actual number ends and
where the fuzz begins. You can do it visually, and the algorithms
to do it are quite well known.</div></blockquote>
<p>But If I <em>really</em> want my number to be
<code class="docutils literal notranslate"><span class="pre">Decimal('110000000000000008881784197001252...e-51')</span></code>, why cant I
write <code class="docutils literal notranslate"><span class="pre">Decimal(1.1)</span></code>? Why should I expect Decimal to be “rounding”
it? Remember that <code class="docutils literal notranslate"><span class="pre">1.1</span></code> <em>is</em> binary floating point, so I can
predict the result. Its not intuitive to a beginner, but thats the
way it is.</p>
<p>Anyway, Paul Moore showed that (1) cant work, because:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> <span class="n">says</span> <span class="n">D</span><span class="p">(</span><span class="mf">1.1</span><span class="p">)</span> <span class="o">==</span> <span class="n">D</span><span class="p">(</span><span class="s1">&#39;1.1&#39;</span><span class="p">)</span>
<span class="n">but</span> <span class="mf">1.1</span> <span class="o">==</span> <span class="mf">1.1000000000000001</span>
<span class="n">so</span> <span class="n">D</span><span class="p">(</span><span class="mf">1.1</span><span class="p">)</span> <span class="o">==</span> <span class="n">D</span><span class="p">(</span><span class="mf">1.1000000000000001</span><span class="p">)</span>
<span class="n">together</span><span class="p">:</span> <span class="n">D</span><span class="p">(</span><span class="mf">1.1000000000000001</span><span class="p">)</span> <span class="o">==</span> <span class="n">D</span><span class="p">(</span><span class="s1">&#39;1.1&#39;</span><span class="p">)</span>
</pre></div>
</div>
<p>which is wrong, because if I write <code class="docutils literal notranslate"><span class="pre">Decimal('1.1')</span></code> it is exact, not
<code class="docutils literal notranslate"><span class="pre">D(1.1000000000000001)</span></code>. He also proposed to have an explicit
conversion to float. bokr says you need to put the precision in the
constructor and mwilson agreed:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">d</span> <span class="o">=</span> <span class="n">Decimal</span> <span class="p">(</span><span class="mf">1.1</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span> <span class="c1"># take float value to 1 decimal place</span>
<span class="n">d</span> <span class="o">=</span> <span class="n">Decimal</span> <span class="p">(</span><span class="mf">1.1</span><span class="p">)</span> <span class="c1"># gets `places` from pre-set context</span>
</pre></div>
</div>
<p>But Alex Martelli says that:</p>
<blockquote>
<div>Constructing with some specified precision would be fine. Thus,
I think “construction from float with some default precision” runs
a substantial risk of tricking naive users.</div></blockquote>
<p>So, the accepted solution through c.l.p is that you can not call Decimal
with a float. Instead you must use a method: Decimal.from_float(). The
syntax:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">Decimal</span><span class="o">.</span><span class="n">from_float</span><span class="p">(</span><span class="n">floatNumber</span><span class="p">,</span> <span class="p">[</span><span class="n">decimal_places</span><span class="p">])</span>
</pre></div>
</div>
<p>where <code class="docutils literal notranslate"><span class="pre">floatNumber</span></code> is the float number origin of the construction
and <code class="docutils literal notranslate"><span class="pre">decimal_places</span></code> are the number of digits after the decimal
point where you apply a round-half-up rounding, if any. In this way
you can do, for example:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">Decimal</span><span class="o">.</span><span class="n">from_float</span><span class="p">(</span><span class="mf">1.1</span><span class="p">,</span> <span class="mi">2</span><span class="p">):</span> <span class="n">The</span> <span class="n">same</span> <span class="k">as</span> <span class="n">doing</span> <span class="n">Decimal</span><span class="p">(</span><span class="s1">&#39;1.1&#39;</span><span class="p">)</span><span class="o">.</span>
<span class="n">Decimal</span><span class="o">.</span><span class="n">from_float</span><span class="p">(</span><span class="mf">1.1</span><span class="p">,</span> <span class="mi">16</span><span class="p">):</span> <span class="n">The</span> <span class="n">same</span> <span class="k">as</span> <span class="n">doing</span> <span class="n">Decimal</span><span class="p">(</span><span class="s1">&#39;1.1000000000000001&#39;</span><span class="p">)</span><span class="o">.</span>
<span class="n">Decimal</span><span class="o">.</span><span class="n">from_float</span><span class="p">(</span><span class="mf">1.1</span><span class="p">):</span> <span class="n">The</span> <span class="n">same</span> <span class="k">as</span> <span class="n">doing</span> <span class="n">Decimal</span><span class="p">(</span><span class="s1">&#39;1100000000000000088817841970012523233890533447265625e-51&#39;</span><span class="p">)</span><span class="o">.</span>
</pre></div>
</div>
<p>Based on later discussions, it was decided to omit from_float() from the
API for Py2.4. Several ideas contributed to the thought process:</p>
<ul>
<li>Interactions between decimal and binary floating point force the user to
deal with tricky issues of representation and round-off. Avoidance of those
issues is a primary reason for having the module in the first place.</li>
<li>The first release of the module should focus on that which is safe, minimal,
and essential.</li>
<li>While theoretically nice, real world use cases for interactions between floats
and decimals are lacking. Java included float/decimal conversions to handle
an obscure case where calculations are best performed in decimal even though
a legacy data structure requires the inputs and outputs to be stored in
binary floating point.</li>
<li>If the need arises, users can use string representations as an intermediate
type. The advantage of this approach is that it makes explicit the
assumptions about precision and representation (no wondering what is going
on under the hood).</li>
<li>The Java docs for BigDecimal(double val) reflected their experiences with
the constructor:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">The</span> <span class="n">results</span> <span class="n">of</span> <span class="n">this</span> <span class="n">constructor</span> <span class="n">can</span> <span class="n">be</span> <span class="n">somewhat</span>
<span class="n">unpredictable</span> <span class="ow">and</span> <span class="n">its</span> <span class="n">use</span> <span class="ow">is</span> <span class="n">generally</span> <span class="ow">not</span> <span class="n">recommended</span><span class="o">.</span>
</pre></div>
</div>
</li>
</ul>
</section>
<section id="from-tuples">
<h4><a class="toc-backref" href="#from-tuples" role="doc-backlink">From tuples</a></h4>
<p>Aahz suggested to construct from tuples: its easier
to implement <code class="docutils literal notranslate"><span class="pre">eval()</span></code>s round trip and “someone who has numeric
values representing a Decimal does not need to convert them to a
string.”</p>
<p>The structure will be a tuple of three elements: sign, number and
exponent. The sign is 1 or 0, the number is a tuple of decimal digits
and the exponent is a signed int or long:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">Decimal</span><span class="p">((</span><span class="mi">1</span><span class="p">,</span> <span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">5</span><span class="p">),</span> <span class="o">-</span><span class="mi">2</span><span class="p">))</span> <span class="c1"># for -32.25</span>
</pre></div>
</div>
<p>Of course, you can construct in this way all special values:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">Decimal</span><span class="p">(</span> <span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="p">(</span><span class="mi">0</span><span class="p">,),</span> <span class="s1">&#39;F&#39;</span><span class="p">)</span> <span class="p">)</span> <span class="c1"># for Infinity</span>
<span class="n">Decimal</span><span class="p">(</span> <span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="p">(</span><span class="mi">0</span><span class="p">,),</span> <span class="s1">&#39;n&#39;</span><span class="p">)</span> <span class="p">)</span> <span class="c1"># for Not a Number</span>
</pre></div>
</div>
</section>
<section id="from-decimal">
<h4><a class="toc-backref" href="#from-decimal" role="doc-backlink">From Decimal</a></h4>
<p>No mystery here, just a copy.</p>
</section>
<section id="syntax-for-all-cases">
<h4><a class="toc-backref" href="#syntax-for-all-cases" role="doc-backlink">Syntax for All Cases</a></h4>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">Decimal</span><span class="p">(</span><span class="n">value1</span><span class="p">)</span>
<span class="n">Decimal</span><span class="o">.</span><span class="n">from_float</span><span class="p">(</span><span class="n">value2</span><span class="p">,</span> <span class="p">[</span><span class="n">decimal_places</span><span class="p">])</span>
</pre></div>
</div>
<p>where <code class="docutils literal notranslate"><span class="pre">value1</span></code> can be int, long, string, 3-tuple or Decimal,
<code class="docutils literal notranslate"><span class="pre">value2</span></code> can only be float, and <code class="docutils literal notranslate"><span class="pre">decimal_places</span></code> is an optional
non negative int.</p>
</section>
<section id="creating-from-context">
<h4><a class="toc-backref" href="#creating-from-context" role="doc-backlink">Creating from Context</a></h4>
<p>This item arose in python-dev from two sources in parallel. Ka-Ping
Yee proposes to pass the context as an argument at instance creation
(he wants the context he passes to be used only in creation time: “It
would not be persistent”). Tony Meyer asks from_string to honor the
context if it receives a parameter “honour_context” with a True value.
(I dont like it, because the doc specifies that the context be
honored and I dont want the method to comply with the specification
regarding the value of an argument.)</p>
<p>Tim Peters gives us a reason to have a creation that uses context:</p>
<blockquote>
<div>In general number-crunching, literals may be given to high
precision, but that precision isnt free and <em>usually</em> isnt
needed</div></blockquote>
<p>Casey Duncan wants to use another method, not a bool arg:</p>
<blockquote>
<div>I find boolean arguments a general anti-pattern, especially given
we have class methods. Why not use an alternate constructor like
Decimal.rounded_to_context(“3.14159265”).</div></blockquote>
<p>In the process of deciding the syntax of that, Tim came up with a
better idea: he proposes not to have a method in Decimal to create
with a different context, but having instead a method in Context to
create a Decimal instance. Basically, instead of:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">D</span><span class="o">.</span><span class="n">using_context</span><span class="p">(</span><span class="n">number</span><span class="p">,</span> <span class="n">context</span><span class="p">)</span>
</pre></div>
</div>
<p>it will be:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">context</span><span class="o">.</span><span class="n">create_decimal</span><span class="p">(</span><span class="n">number</span><span class="p">)</span>
</pre></div>
</div>
<p>From Tim:</p>
<blockquote>
<div>While all operations in the spec except for the two to-string
operations use context, no operations in the spec support an
optional local context. That the Decimal() constructor ignores
context by default is an extension to the spec. We must supply a
context-honoring from-string operation to meet the spec. I
recommend against any concept of “local context” in any operation
it complicates the model and isnt necessary.</div></blockquote>
<p>So, we decided to use a context method to create a Decimal that will
use (only to be created) that context in particular (for further
operations it will use the context of the thread). But, a method with
what name?</p>
<p>Tim Peters proposes three methods to create from diverse sources
(from_string, from_int, from_float). I proposed to use one method,
<code class="docutils literal notranslate"><span class="pre">create_decimal()</span></code>, without caring about the data type. Michael
Chermside: “The name just fits my brain. The fact that it uses the
context is obvious from the fact that its Context method”.</p>
<p>The community agreed with that. I think that its OK because a newbie
will not be using the creation method from Context (the separate
method in Decimal to construct from float is just to prevent newbies
from encountering binary floating point issues).</p>
<p>So, in short, if you want to create a Decimal instance using a
particular context (that will be used just at creation time and not
any further), youll have to use a method of that context:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1"># n is any datatype accepted in Decimal(n) plus float</span>
<span class="n">mycontext</span><span class="o">.</span><span class="n">create_decimal</span><span class="p">(</span><span class="n">n</span><span class="p">)</span>
</pre></div>
</div>
<p>Example:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="c1"># create a standard decimal instance</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">Decimal</span><span class="p">(</span><span class="s2">&quot;11.2233445566778899&quot;</span><span class="p">)</span>
<span class="go">Decimal(&quot;11.2233445566778899&quot;)</span>
<span class="gp">&gt;&gt;&gt;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="c1"># create a decimal instance using the thread context</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">thread_context</span> <span class="o">=</span> <span class="n">getcontext</span><span class="p">()</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">thread_context</span><span class="o">.</span><span class="n">prec</span>
<span class="go">28</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">thread_context</span><span class="o">.</span><span class="n">create_decimal</span><span class="p">(</span><span class="s2">&quot;11.2233445566778899&quot;</span><span class="p">)</span>
<span class="go">Decimal(&quot;11.2233445566778899&quot;)</span>
<span class="gp">&gt;&gt;&gt;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="c1"># create a decimal instance using other context</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">other_context</span> <span class="o">=</span> <span class="n">thread_context</span><span class="o">.</span><span class="n">copy</span><span class="p">()</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">other_context</span><span class="o">.</span><span class="n">prec</span> <span class="o">=</span> <span class="mi">4</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">other_context</span><span class="o">.</span><span class="n">create_decimal</span><span class="p">(</span><span class="s2">&quot;11.2233445566778899&quot;</span><span class="p">)</span>
<span class="go">Decimal(&quot;11.22&quot;)</span>
</pre></div>
</div>
</section>
</section>
<section id="implicit-construction">
<h3><a class="toc-backref" href="#implicit-construction" role="doc-backlink">Implicit construction</a></h3>
<p>As the implicit construction is the consequence of an operation, it
will be affected by the context as is detailed in each point.</p>
<p>John Roth suggested that “The other type should be handled in the same
way the decimal() constructor would handle it”. But Alex Martelli
thinks that</p>
<blockquote>
<div>this total breach with Python tradition would be a terrible
mistake. 23+”43” is NOT handled in the same way as 23+int(“45”),
and a VERY good thing that is too. Its a completely different
thing for a user to EXPLICITLY indicate they want construction
(conversion) and to just happen to sum two objects one of which by
mistake could be a string.</div></blockquote>
<p>So, here I define the behaviour again for each data type.</p>
<section id="id15">
<h4><a class="toc-backref" href="#id15" role="doc-backlink">From int or long</a></h4>
<p>An int or long is a treated like a Decimal explicitly constructed from
Decimal(str(x)) in the current context (meaning that the to-string rules
for rounding are applied and the appropriate flags are set). This
guarantees that expressions like <code class="docutils literal notranslate"><span class="pre">Decimal('1234567')</span> <span class="pre">+</span> <span class="pre">13579</span></code> match
the mental model of <code class="docutils literal notranslate"><span class="pre">Decimal('1234567')</span> <span class="pre">+</span> <span class="pre">Decimal('13579')</span></code>. That
model works because all integers are representable as strings without
representation error.</p>
</section>
<section id="id16">
<h4><a class="toc-backref" href="#id16" role="doc-backlink">From string</a></h4>
<p>Everybody agrees to raise an exception here.</p>
</section>
<section id="id17">
<h4><a class="toc-backref" href="#id17" role="doc-backlink">From float</a></h4>
<p>Aahz is strongly opposed to interact with float, suggesting an
explicit conversion:</p>
<blockquote>
<div>The problem is that Decimal is capable of greater precision,
accuracy, and range than float.</div></blockquote>
<p>The example of the valid python expression, <code class="docutils literal notranslate"><span class="pre">35</span> <span class="pre">+</span> <span class="pre">1.1</span></code>, seems to suggest
that <code class="docutils literal notranslate"><span class="pre">Decimal(35)</span> <span class="pre">+</span> <span class="pre">1.1</span></code> should also be valid. However, a closer look
shows that it only demonstrates the feasibility of integer to floating
point conversions. Hence, the correct analog for decimal floating point
is <code class="docutils literal notranslate"><span class="pre">35</span> <span class="pre">+</span> <span class="pre">Decimal(1.1)</span></code>. Both coercions, int-to-float and int-to-Decimal,
can be done without incurring representation error.</p>
<p>The question of how to coerce between binary and decimal floating point
is more complex. I proposed allowing the interaction with float,
making an exact conversion and raising ValueError if exceeds the
precision in the current context (this is maybe too tricky, because
for example with a precision of 9, <code class="docutils literal notranslate"><span class="pre">Decimal(35)</span> <span class="pre">+</span> <span class="pre">1.2</span></code> is OK but
<code class="docutils literal notranslate"><span class="pre">Decimal(35)</span> <span class="pre">+</span> <span class="pre">1.1</span></code> raises an error).</p>
<p>This resulted to be too tricky. So tricky, that c.l.p agreed to raise
TypeError in this case: you could not mix Decimal and float.</p>
</section>
<section id="id18">
<h4><a class="toc-backref" href="#id18" role="doc-backlink">From Decimal</a></h4>
<p>There isnt any issue here.</p>
</section>
</section>
<section id="use-of-context">
<h3><a class="toc-backref" href="#use-of-context" role="doc-backlink">Use of Context</a></h3>
<p>In the last pre-PEP I said that “The Context must be omnipresent,
meaning that changes to it affects all the current and future Decimal
instances”. I was wrong. In response, John Roth said:</p>
<blockquote>
<div>The context should be selectable for the particular usage. That
is, it should be possible to have several different contexts in
play at one time in an application.</div></blockquote>
<p>In comp.lang.python, Aahz explained that the idea is to have a
“context per thread”. So, all the instances of a thread belongs to a
context, and you can change a context in thread A (and the behaviour
of the instances of that thread) without changing nothing in thread B.</p>
<p>Also, and again correcting me, he said:</p>
<blockquote>
<div>(the) Context applies only to operations, not to Decimal
instances; changing the Context does not affect existing instances
if there are no operations on them.</div></blockquote>
<p>Arguing about special cases when theres need to perform operations
with other rules that those of the current context, Tim Peters said
that the context will have the operations as methods. This way, the
user “can create whatever private context object(s) it needs, and
spell arithmetic as explicit method calls on its private context
object(s), so that the default thread context object is neither
consulted nor modified”.</p>
</section>
<section id="python-usability">
<h3><a class="toc-backref" href="#python-usability" role="doc-backlink">Python Usability</a></h3>
<ul>
<li>Decimal should support the basic arithmetic (<code class="docutils literal notranslate"><span class="pre">+,</span> <span class="pre">-,</span> <span class="pre">*,</span> <span class="pre">/,</span> <span class="pre">//,</span> <span class="pre">**,</span>
<span class="pre">%,</span> <span class="pre">divmod</span></code>) and comparison (<code class="docutils literal notranslate"><span class="pre">==,</span> <span class="pre">!=,</span> <span class="pre">&lt;,</span> <span class="pre">&gt;,</span> <span class="pre">&lt;=,</span> <span class="pre">&gt;=,</span> <span class="pre">cmp</span></code>)
operators in the following cases (check <a class="reference internal" href="#implicit-construction">Implicit Construction</a> to
see what types could OtherType be, and what happens in each case):<ul class="simple">
<li>Decimal op Decimal</li>
<li>Decimal op otherType</li>
<li>otherType op Decimal</li>
<li>Decimal op= Decimal</li>
<li>Decimal op= otherType</li>
</ul>
</li>
<li>Decimal should support unary operators (<code class="docutils literal notranslate"><span class="pre">-,</span> <span class="pre">+,</span> <span class="pre">abs</span></code>).</li>
<li>repr() should round trip, meaning that:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">m</span> <span class="o">=</span> <span class="n">Decimal</span><span class="p">(</span><span class="o">...</span><span class="p">)</span>
<span class="n">m</span> <span class="o">==</span> <span class="nb">eval</span><span class="p">(</span><span class="nb">repr</span><span class="p">(</span><span class="n">m</span><span class="p">))</span>
</pre></div>
</div>
</li>
<li>Decimal should be immutable.</li>
<li>Decimal should support the built-in methods:<ul class="simple">
<li>min, max</li>
<li>float, int, long</li>
<li>str, repr</li>
<li>hash</li>
<li>bool (0 is false, otherwise true)</li>
</ul>
</li>
</ul>
<p>Theres been some discussion in python-dev about the behaviour of
<code class="docutils literal notranslate"><span class="pre">hash()</span></code>. The community agrees that if the values are the same, the
hashes of those values should also be the same. So, while Decimal(25)
== 25 is True, hash(Decimal(25)) should be equal to hash(25).</p>
<p>The detail is that you can NOT compare Decimal to floats or strings,
so we should not worry about them giving the same hashes. In short:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nb">hash</span><span class="p">(</span><span class="n">n</span><span class="p">)</span> <span class="o">==</span> <span class="nb">hash</span><span class="p">(</span><span class="n">Decimal</span><span class="p">(</span><span class="n">n</span><span class="p">))</span> <span class="c1"># Only if n is int, long, or Decimal</span>
</pre></div>
</div>
<p>Regarding str() and repr() behaviour, Ka-Ping Yee proposes that repr()
have the same behaviour as str() and Tim Peters proposes that str()
behave like the to-scientific-string operation from the Spec.</p>
<p>This is possible, because (from Aahz): “The string form already
contains all the necessary information to reconstruct a Decimal
object”.</p>
<p>And it also complies with the Spec; Tim Peters:</p>
<blockquote>
<div>Theres no requirement to have a method <em>named</em> “to_sci_string”,
the only requirement is that <em>some</em> way to spell to-sci-strings
functionality be supplied. The meaning of to-sci-string is
precisely specified by the standard, and is a good choice for both
str(Decimal) and repr(Decimal).</div></blockquote>
</section>
</section>
<section id="documentation">
<h2><a class="toc-backref" href="#documentation" role="doc-backlink">Documentation</a></h2>
<p>This section explains all the public methods and attributes of Decimal
and Context.</p>
<section id="decimal-attributes">
<h3><a class="toc-backref" href="#decimal-attributes" role="doc-backlink">Decimal Attributes</a></h3>
<p>Decimal has no public attributes. The internal information is stored
in slots and should not be accessed by end users.</p>
</section>
<section id="decimal-methods">
<h3><a class="toc-backref" href="#decimal-methods" role="doc-backlink">Decimal Methods</a></h3>
<p>Following are the conversion and arithmetic operations defined in the
Spec, and how that functionality can be achieved with the actual
implementation.</p>
<ul>
<li>to-scientific-string: Use builtin function <code class="docutils literal notranslate"><span class="pre">str()</span></code>:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">d</span> <span class="o">=</span> <span class="n">Decimal</span><span class="p">(</span><span class="s1">&#39;123456789012.345&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">str</span><span class="p">(</span><span class="n">d</span><span class="p">)</span>
<span class="go">&#39;1.23456789E+11&#39;</span>
</pre></div>
</div>
</li>
<li>to-engineering-string: Use method <code class="docutils literal notranslate"><span class="pre">to_eng_string()</span></code>:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">d</span> <span class="o">=</span> <span class="n">Decimal</span><span class="p">(</span><span class="s1">&#39;123456789012.345&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">d</span><span class="o">.</span><span class="n">to_eng_string</span><span class="p">()</span>
<span class="go">&#39;123.456789E+9&#39;</span>
</pre></div>
</div>
</li>
<li>to-number: Use Context method <code class="docutils literal notranslate"><span class="pre">create_decimal()</span></code>. The standard
constructor or <code class="docutils literal notranslate"><span class="pre">from_float()</span></code> constructor cannot be used because
these do not use the context (as is specified in the Spec for this
conversion).</li>
<li>abs: Use builtin function <code class="docutils literal notranslate"><span class="pre">abs()</span></code>:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">d</span> <span class="o">=</span> <span class="n">Decimal</span><span class="p">(</span><span class="s1">&#39;-15.67&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">abs</span><span class="p">(</span><span class="n">d</span><span class="p">)</span>
<span class="go">Decimal(&#39;15.67&#39;)</span>
</pre></div>
</div>
</li>
<li>add: Use operator <code class="docutils literal notranslate"><span class="pre">+</span></code>:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">d</span> <span class="o">=</span> <span class="n">Decimal</span><span class="p">(</span><span class="s1">&#39;15.6&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">d</span> <span class="o">+</span> <span class="mi">8</span>
<span class="go">Decimal(&#39;23.6&#39;)</span>
</pre></div>
</div>
</li>
<li>subtract: Use operator <code class="docutils literal notranslate"><span class="pre">-</span></code>:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">d</span> <span class="o">=</span> <span class="n">Decimal</span><span class="p">(</span><span class="s1">&#39;15.6&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">d</span> <span class="o">-</span> <span class="mi">8</span>
<span class="go">Decimal(&#39;7.6&#39;)</span>
</pre></div>
</div>
</li>
<li>compare: Use method <code class="docutils literal notranslate"><span class="pre">compare()</span></code>. This method (and not the
built-in function cmp()) should only be used when dealing with
<em>special values</em>:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">d</span> <span class="o">=</span> <span class="n">Decimal</span><span class="p">(</span><span class="s1">&#39;-15.67&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">nan</span> <span class="o">=</span> <span class="n">Decimal</span><span class="p">(</span><span class="s1">&#39;NaN&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">d</span><span class="o">.</span><span class="n">compare</span><span class="p">(</span><span class="mi">23</span><span class="p">)</span>
<span class="go">&#39;-1&#39;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">d</span><span class="o">.</span><span class="n">compare</span><span class="p">(</span><span class="n">nan</span><span class="p">)</span>
<span class="go">&#39;NaN&#39;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">cmp</span><span class="p">(</span><span class="n">d</span><span class="p">,</span> <span class="mi">23</span><span class="p">)</span>
<span class="go">-1</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">cmp</span><span class="p">(</span><span class="n">d</span><span class="p">,</span> <span class="n">nan</span><span class="p">)</span>
<span class="go">1</span>
</pre></div>
</div>
</li>
<li>divide: Use operator <code class="docutils literal notranslate"><span class="pre">/</span></code>:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">d</span> <span class="o">=</span> <span class="n">Decimal</span><span class="p">(</span><span class="s1">&#39;-15.67&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">d</span> <span class="o">/</span> <span class="mi">2</span>
<span class="go">Decimal(&#39;-7.835&#39;)</span>
</pre></div>
</div>
</li>
<li>divide-integer: Use operator <code class="docutils literal notranslate"><span class="pre">//</span></code>:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">d</span> <span class="o">=</span> <span class="n">Decimal</span><span class="p">(</span><span class="s1">&#39;-15.67&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">d</span> <span class="o">//</span> <span class="mi">2</span>
<span class="go">Decimal(&#39;-7&#39;)</span>
</pre></div>
</div>
</li>
<li>max: Use method <code class="docutils literal notranslate"><span class="pre">max()</span></code>. Only use this method (and not the
built-in function max()) when dealing with <em>special values</em>:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">d</span> <span class="o">=</span> <span class="n">Decimal</span><span class="p">(</span><span class="s1">&#39;15&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">nan</span> <span class="o">=</span> <span class="n">Decimal</span><span class="p">(</span><span class="s1">&#39;NaN&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">d</span><span class="o">.</span><span class="n">max</span><span class="p">(</span><span class="mi">8</span><span class="p">)</span>
<span class="go">Decimal(&#39;15&#39;)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">d</span><span class="o">.</span><span class="n">max</span><span class="p">(</span><span class="n">nan</span><span class="p">)</span>
<span class="go">Decimal(&#39;NaN&#39;)</span>
</pre></div>
</div>
</li>
<li>min: Use method <code class="docutils literal notranslate"><span class="pre">min()</span></code>. Only use this method (and not the
built-in function min()) when dealing with <em>special values</em>:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">d</span> <span class="o">=</span> <span class="n">Decimal</span><span class="p">(</span><span class="s1">&#39;15&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">nan</span> <span class="o">=</span> <span class="n">Decimal</span><span class="p">(</span><span class="s1">&#39;NaN&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">d</span><span class="o">.</span><span class="n">min</span><span class="p">(</span><span class="mi">8</span><span class="p">)</span>
<span class="go">Decimal(&#39;8&#39;)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">d</span><span class="o">.</span><span class="n">min</span><span class="p">(</span><span class="n">nan</span><span class="p">)</span>
<span class="go">Decimal(&#39;NaN&#39;)</span>
</pre></div>
</div>
</li>
<li>minus: Use unary operator <code class="docutils literal notranslate"><span class="pre">-</span></code>:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">d</span> <span class="o">=</span> <span class="n">Decimal</span><span class="p">(</span><span class="s1">&#39;-15.67&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="o">-</span><span class="n">d</span>
<span class="go">Decimal(&#39;15.67&#39;)</span>
</pre></div>
</div>
</li>
<li>plus: Use unary operator <code class="docutils literal notranslate"><span class="pre">+</span></code>:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">d</span> <span class="o">=</span> <span class="n">Decimal</span><span class="p">(</span><span class="s1">&#39;-15.67&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="o">+</span><span class="n">d</span>
<span class="go">Decimal(&#39;-15.67&#39;)</span>
</pre></div>
</div>
</li>
<li>multiply: Use operator <code class="docutils literal notranslate"><span class="pre">*</span></code>:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">d</span> <span class="o">=</span> <span class="n">Decimal</span><span class="p">(</span><span class="s1">&#39;5.7&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">d</span> <span class="o">*</span> <span class="mi">3</span>
<span class="go">Decimal(&#39;17.1&#39;)</span>
</pre></div>
</div>
</li>
<li>normalize: Use method <code class="docutils literal notranslate"><span class="pre">normalize()</span></code>:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">d</span> <span class="o">=</span> <span class="n">Decimal</span><span class="p">(</span><span class="s1">&#39;123.45000&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">d</span><span class="o">.</span><span class="n">normalize</span><span class="p">()</span>
<span class="go">Decimal(&#39;123.45&#39;)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">d</span> <span class="o">=</span> <span class="n">Decimal</span><span class="p">(</span><span class="s1">&#39;120.00&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">d</span><span class="o">.</span><span class="n">normalize</span><span class="p">()</span>
<span class="go">Decimal(&#39;1.2E+2&#39;)</span>
</pre></div>
</div>
</li>
<li>quantize: Use method <code class="docutils literal notranslate"><span class="pre">quantize()</span></code>:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">d</span> <span class="o">=</span> <span class="n">Decimal</span><span class="p">(</span><span class="s1">&#39;2.17&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">d</span><span class="o">.</span><span class="n">quantize</span><span class="p">(</span><span class="n">Decimal</span><span class="p">(</span><span class="s1">&#39;0.001&#39;</span><span class="p">))</span>
<span class="go">Decimal(&#39;2.170&#39;)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">d</span><span class="o">.</span><span class="n">quantize</span><span class="p">(</span><span class="n">Decimal</span><span class="p">(</span><span class="s1">&#39;0.1&#39;</span><span class="p">))</span>
<span class="go">Decimal(&#39;2.2&#39;)</span>
</pre></div>
</div>
</li>
<li>remainder: Use operator <code class="docutils literal notranslate"><span class="pre">%</span></code>:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">d</span> <span class="o">=</span> <span class="n">Decimal</span><span class="p">(</span><span class="s1">&#39;10&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">d</span> <span class="o">%</span> <span class="mi">3</span>
<span class="go">Decimal(&#39;1&#39;)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">d</span> <span class="o">%</span> <span class="mi">6</span>
<span class="go">Decimal(&#39;4&#39;)</span>
</pre></div>
</div>
</li>
<li>remainder-near: Use method <code class="docutils literal notranslate"><span class="pre">remainder_near()</span></code>:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">d</span> <span class="o">=</span> <span class="n">Decimal</span><span class="p">(</span><span class="s1">&#39;10&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">d</span><span class="o">.</span><span class="n">remainder_near</span><span class="p">(</span><span class="mi">3</span><span class="p">)</span>
<span class="go">Decimal(&#39;1&#39;)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">d</span><span class="o">.</span><span class="n">remainder_near</span><span class="p">(</span><span class="mi">6</span><span class="p">)</span>
<span class="go">Decimal(&#39;-2&#39;)</span>
</pre></div>
</div>
</li>
<li>round-to-integral-value: Use method <code class="docutils literal notranslate"><span class="pre">to_integral()</span></code>:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">d</span> <span class="o">=</span> <span class="n">Decimal</span><span class="p">(</span><span class="s1">&#39;-123.456&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">d</span><span class="o">.</span><span class="n">to_integral</span><span class="p">()</span>
<span class="go">Decimal(&#39;-123&#39;)</span>
</pre></div>
</div>
</li>
<li>same-quantum: Use method <code class="docutils literal notranslate"><span class="pre">same_quantum()</span></code>:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">d</span> <span class="o">=</span> <span class="n">Decimal</span><span class="p">(</span><span class="s1">&#39;123.456&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">d</span><span class="o">.</span><span class="n">same_quantum</span><span class="p">(</span><span class="n">Decimal</span><span class="p">(</span><span class="s1">&#39;0.001&#39;</span><span class="p">))</span>
<span class="go">True</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">d</span><span class="o">.</span><span class="n">same_quantum</span><span class="p">(</span><span class="n">Decimal</span><span class="p">(</span><span class="s1">&#39;0.01&#39;</span><span class="p">))</span>
<span class="go">False</span>
</pre></div>
</div>
</li>
<li>square-root: Use method <code class="docutils literal notranslate"><span class="pre">sqrt()</span></code>:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">d</span> <span class="o">=</span> <span class="n">Decimal</span><span class="p">(</span><span class="s1">&#39;123.456&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">d</span><span class="o">.</span><span class="n">sqrt</span><span class="p">()</span>
<span class="go">Decimal(&#39;11.1110756&#39;)</span>
</pre></div>
</div>
</li>
<li>power: User operator <code class="docutils literal notranslate"><span class="pre">**</span></code>:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">d</span> <span class="o">=</span> <span class="n">Decimal</span><span class="p">(</span><span class="s1">&#39;12.56&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">d</span> <span class="o">**</span> <span class="mi">2</span>
<span class="go">Decimal(&#39;157.7536&#39;)</span>
</pre></div>
</div>
</li>
</ul>
<p>Following are other methods and why they exist:</p>
<ul>
<li><code class="docutils literal notranslate"><span class="pre">adjusted()</span></code>: Returns the adjusted exponent. This concept is
defined in the Spec: the adjusted exponent is the value of the
exponent of a number when that number is expressed as though in
scientific notation with one digit before any decimal point:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">d</span> <span class="o">=</span> <span class="n">Decimal</span><span class="p">(</span><span class="s1">&#39;12.56&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">d</span><span class="o">.</span><span class="n">adjusted</span><span class="p">()</span>
<span class="go">1</span>
</pre></div>
</div>
</li>
<li><code class="docutils literal notranslate"><span class="pre">from_float()</span></code>: Class method to create instances from float data
types:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">d</span> <span class="o">=</span> <span class="n">Decimal</span><span class="o">.</span><span class="n">from_float</span><span class="p">(</span><span class="mf">12.35</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">d</span>
<span class="go">Decimal(&#39;12.3500000&#39;)</span>
</pre></div>
</div>
</li>
<li><code class="docutils literal notranslate"><span class="pre">as_tuple()</span></code>: Show the internal structure of the Decimal, the
triple tuple. This method is not required by the Spec, but Tim
Peters proposed it and the community agreed to have it (its useful
for developing and debugging):<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">d</span> <span class="o">=</span> <span class="n">Decimal</span><span class="p">(</span><span class="s1">&#39;123.4&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">d</span><span class="o">.</span><span class="n">as_tuple</span><span class="p">()</span>
<span class="go">(0, (1, 2, 3, 4), -1)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">d</span> <span class="o">=</span> <span class="n">Decimal</span><span class="p">(</span><span class="s1">&#39;-2.34e5&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">d</span><span class="o">.</span><span class="n">as_tuple</span><span class="p">()</span>
<span class="go">(1, (2, 3, 4), 3)</span>
</pre></div>
</div>
</li>
</ul>
</section>
<section id="context-attributes">
<h3><a class="toc-backref" href="#context-attributes" role="doc-backlink">Context Attributes</a></h3>
<p>These are the attributes that can be changed to modify the context.</p>
<ul>
<li><code class="docutils literal notranslate"><span class="pre">prec</span></code> (int): the precision:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">c</span><span class="o">.</span><span class="n">prec</span>
<span class="go">9</span>
</pre></div>
</div>
</li>
<li><code class="docutils literal notranslate"><span class="pre">rounding</span></code> (str): rounding type (how to round):<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">c</span><span class="o">.</span><span class="n">rounding</span>
<span class="go">&#39;half_even&#39;</span>
</pre></div>
</div>
</li>
<li><code class="docutils literal notranslate"><span class="pre">trap_enablers</span></code> (dict): if trap_enablers[exception] = 1, then an
exception is raised when it is caused:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">c</span><span class="o">.</span><span class="n">trap_enablers</span><span class="p">[</span><span class="n">Underflow</span><span class="p">]</span>
<span class="go">0</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">c</span><span class="o">.</span><span class="n">trap_enablers</span><span class="p">[</span><span class="n">Clamped</span><span class="p">]</span>
<span class="go">0</span>
</pre></div>
</div>
</li>
<li><code class="docutils literal notranslate"><span class="pre">flags</span></code> (dict): when an exception is caused, flags[exception] is
incremented (whether or not the trap_enabler is set). Should be
reset by the user of Decimal instance:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">c</span><span class="o">.</span><span class="n">flags</span><span class="p">[</span><span class="n">Underflow</span><span class="p">]</span>
<span class="go">0</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">c</span><span class="o">.</span><span class="n">flags</span><span class="p">[</span><span class="n">Clamped</span><span class="p">]</span>
<span class="go">0</span>
</pre></div>
</div>
</li>
<li><code class="docutils literal notranslate"><span class="pre">Emin</span></code> (int): minimum exponent:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">c</span><span class="o">.</span><span class="n">Emin</span>
<span class="go">-999999999</span>
</pre></div>
</div>
</li>
<li><code class="docutils literal notranslate"><span class="pre">Emax</span></code> (int): maximum exponent:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">c</span><span class="o">.</span><span class="n">Emax</span>
<span class="go">999999999</span>
</pre></div>
</div>
</li>
<li><code class="docutils literal notranslate"><span class="pre">capitals</span></code> (int): boolean flag to use E (True/1) or e
(False/0) in the string (for example, 1.32e+2 or 1.32E+2):<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">c</span><span class="o">.</span><span class="n">capitals</span>
<span class="go">1</span>
</pre></div>
</div>
</li>
</ul>
</section>
<section id="context-methods">
<h3><a class="toc-backref" href="#context-methods" role="doc-backlink">Context Methods</a></h3>
<p>The following methods comply with Decimal functionality from the Spec.
Be aware that the operations that are called through a specific
context use that context and not the thread context.</p>
<p>To use these methods, take note that the syntax changes when the
operator is binary or unary, for example:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">mycontext</span><span class="o">.</span><span class="n">abs</span><span class="p">(</span><span class="n">Decimal</span><span class="p">(</span><span class="s1">&#39;-2&#39;</span><span class="p">))</span>
<span class="go">&#39;2&#39;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">mycontext</span><span class="o">.</span><span class="n">multiply</span><span class="p">(</span><span class="n">Decimal</span><span class="p">(</span><span class="s1">&#39;2.3&#39;</span><span class="p">),</span> <span class="mi">5</span><span class="p">)</span>
<span class="go">&#39;11.5&#39;</span>
</pre></div>
</div>
<p>So, the following are the Spec operations and conversions and how to
achieve them through a context (where <code class="docutils literal notranslate"><span class="pre">d</span></code> is a Decimal instance and
<code class="docutils literal notranslate"><span class="pre">n</span></code> a number that can be used in an <a class="reference internal" href="#implicit-construction">Implicit construction</a>):</p>
<ul class="simple">
<li>to-scientific-string: <code class="docutils literal notranslate"><span class="pre">to_sci_string(d)</span></code></li>
<li>to-engineering-string: <code class="docutils literal notranslate"><span class="pre">to_eng_string(d)</span></code></li>
<li>to-number: <code class="docutils literal notranslate"><span class="pre">create_decimal(number)</span></code>, see <a class="reference internal" href="#explicit-construction">Explicit construction</a>
for <code class="docutils literal notranslate"><span class="pre">number</span></code>.</li>
<li>abs: <code class="docutils literal notranslate"><span class="pre">abs(d)</span></code></li>
<li>add: <code class="docutils literal notranslate"><span class="pre">add(d,</span> <span class="pre">n)</span></code></li>
<li>subtract: <code class="docutils literal notranslate"><span class="pre">subtract(d,</span> <span class="pre">n)</span></code></li>
<li>compare: <code class="docutils literal notranslate"><span class="pre">compare(d,</span> <span class="pre">n)</span></code></li>
<li>divide: <code class="docutils literal notranslate"><span class="pre">divide(d,</span> <span class="pre">n)</span></code></li>
<li>divide-integer: <code class="docutils literal notranslate"><span class="pre">divide_int(d,</span> <span class="pre">n)</span></code></li>
<li>max: <code class="docutils literal notranslate"><span class="pre">max(d,</span> <span class="pre">n)</span></code></li>
<li>min: <code class="docutils literal notranslate"><span class="pre">min(d,</span> <span class="pre">n)</span></code></li>
<li>minus: <code class="docutils literal notranslate"><span class="pre">minus(d)</span></code></li>
<li>plus: <code class="docutils literal notranslate"><span class="pre">plus(d)</span></code></li>
<li>multiply: <code class="docutils literal notranslate"><span class="pre">multiply(d,</span> <span class="pre">n)</span></code></li>
<li>normalize: <code class="docutils literal notranslate"><span class="pre">normalize(d)</span></code></li>
<li>quantize: <code class="docutils literal notranslate"><span class="pre">quantize(d,</span> <span class="pre">d)</span></code></li>
<li>remainder: <code class="docutils literal notranslate"><span class="pre">remainder(d)</span></code></li>
<li>remainder-near: <code class="docutils literal notranslate"><span class="pre">remainder_near(d)</span></code></li>
<li>round-to-integral-value: <code class="docutils literal notranslate"><span class="pre">to_integral(d)</span></code></li>
<li>same-quantum: <code class="docutils literal notranslate"><span class="pre">same_quantum(d,</span> <span class="pre">d)</span></code></li>
<li>square-root: <code class="docutils literal notranslate"><span class="pre">sqrt(d)</span></code></li>
<li>power: <code class="docutils literal notranslate"><span class="pre">power(d,</span> <span class="pre">n)</span></code></li>
</ul>
<p>The <code class="docutils literal notranslate"><span class="pre">divmod(d,</span> <span class="pre">n)</span></code> method supports decimal functionality through
Context.</p>
<p>These are methods that return useful information from the Context:</p>
<ul>
<li><code class="docutils literal notranslate"><span class="pre">Etiny()</span></code>: Minimum exponent considering precision.<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">c</span><span class="o">.</span><span class="n">Emin</span>
<span class="go">-999999999</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">c</span><span class="o">.</span><span class="n">Etiny</span><span class="p">()</span>
<span class="go">-1000000007</span>
</pre></div>
</div>
</li>
<li><code class="docutils literal notranslate"><span class="pre">Etop()</span></code>: Maximum exponent considering precision.<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">c</span><span class="o">.</span><span class="n">Emax</span>
<span class="go">999999999</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">c</span><span class="o">.</span><span class="n">Etop</span><span class="p">()</span>
<span class="go">999999991</span>
</pre></div>
</div>
</li>
<li><code class="docutils literal notranslate"><span class="pre">copy()</span></code>: Returns a copy of the context.</li>
</ul>
</section>
</section>
<section id="reference-implementation">
<h2><a class="toc-backref" href="#reference-implementation" role="doc-backlink">Reference Implementation</a></h2>
<p>As of Python 2.4-alpha, the code has been checked into the standard
library. The latest version is available from:</p>
<p><a class="reference external" href="http://svn.python.org/view/python/trunk/Lib/decimal.py">http://svn.python.org/view/python/trunk/Lib/decimal.py</a></p>
<p>The test cases are here:</p>
<p><a class="reference external" href="http://svn.python.org/view/python/trunk/Lib/test/test_decimal.py">http://svn.python.org/view/python/trunk/Lib/test/test_decimal.py</a></p>
</section>
<section id="references">
<h2><a class="toc-backref" href="#references" role="doc-backlink">References</a></h2>
<aside class="footnote-list brackets">
<aside class="footnote brackets" id="id19" role="doc-footnote">
<dt class="label" id="id19">[1]<em> (<a href='#id1'>1</a>, <a href='#id8'>2</a>) </em></dt>
<dd>ANSI standard X3.274-1996 (Programming Language REXX):
<a class="reference external" href="http://www.rexxla.org/Standards/ansi.html">http://www.rexxla.org/Standards/ansi.html</a></aside>
<aside class="footnote brackets" id="id20" role="doc-footnote">
<dt class="label" id="id20">[2]<em> (<a href='#id2'>1</a>, <a href='#id3'>2</a>, <a href='#id5'>3</a>, <a href='#id6'>4</a>, <a href='#id11'>5</a>, <a href='#id12'>6</a>, <a href='#id13'>7</a>, <a href='#id14'>8</a>) </em></dt>
<dd>General Decimal Arithmetic specification (Cowlishaw):
<a class="reference external" href="http://speleotrove.com/decimal/decarith.html">http://speleotrove.com/decimal/decarith.html</a> (related
documents and links at <a class="reference external" href="http://speleotrove.com/decimal/">http://speleotrove.com/decimal/</a>)</aside>
<aside class="footnote brackets" id="id21" role="doc-footnote">
<dt class="label" id="id21">[<a href="#id7">3</a>]</dt>
<dd>ANSI/IEEE standard 854-1987 (Radix-Independent Floating-Point
Arithmetic):
<a class="reference external" href="http://www.cs.berkeley.edu/~ejr/projects/754/private/drafts/854-1987/dir.html">http://www.cs.berkeley.edu/~ejr/projects/754/private/drafts/854-1987/dir.html</a>
(unofficial text; official copies can be ordered from
<a class="reference external" href="http://standards.ieee.org/catalog/ordering.html">http://standards.ieee.org/catalog/ordering.html</a>)</aside>
<aside class="footnote brackets" id="id22" role="doc-footnote">
<dt class="label" id="id22">[<a href="#id4">4</a>]</dt>
<dd>Tim Peters FixedPoint at SourceForge:
<a class="reference external" href="http://fixedpoint.sourceforge.net/">http://fixedpoint.sourceforge.net/</a></aside>
<aside class="footnote brackets" id="id23" role="doc-footnote">
<dt class="label" id="id23">[<a href="#id9">5</a>]</dt>
<dd>IEEE 754 revision:
<a class="reference external" href="http://grouper.ieee.org/groups/754/revision.html">http://grouper.ieee.org/groups/754/revision.html</a></aside>
<aside class="footnote brackets" id="id24" role="doc-footnote">
<dt class="label" id="id24">[<a href="#id10">6</a>]</dt>
<dd>IEEE 754 references:
<a class="reference external" href="http://babbage.cs.qc.edu/courses/cs341/IEEE-754references.html">http://babbage.cs.qc.edu/courses/cs341/IEEE-754references.html</a></aside>
</aside>
</section>
<section id="copyright">
<h2><a class="toc-backref" href="#copyright" role="doc-backlink">Copyright</a></h2>
<p>This document has been placed in the public domain.</p>
</section>
</section>
<hr class="docutils" />
<p>Source: <a class="reference external" href="https://github.com/python/peps/blob/main/peps/pep-0327.rst">https://github.com/python/peps/blob/main/peps/pep-0327.rst</a></p>
<p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0327.rst">2023-09-09 17:39:29 GMT</a></p>
</article>
<nav id="pep-sidebar">
<h2>Contents</h2>
<ul>
<li><a class="reference internal" href="#abstract">Abstract</a></li>
<li><a class="reference internal" href="#motivation">Motivation</a><ul>
<li><a class="reference internal" href="#the-problem-with-binary-float">The problem with binary float</a></li>
<li><a class="reference internal" href="#why-floating-point">Why floating point?</a></li>
<li><a class="reference internal" href="#why-not-rational">Why not rational?</a></li>
<li><a class="reference internal" href="#so-what-do-we-have">So, what do we have?</a></li>
</ul>
</li>
<li><a class="reference internal" href="#general-decimal-arithmetic-specification">General Decimal Arithmetic Specification</a><ul>
<li><a class="reference internal" href="#the-arithmetic-model">The Arithmetic Model</a></li>
<li><a class="reference internal" href="#numbers">Numbers</a></li>
<li><a class="reference internal" href="#context">Context</a></li>
<li><a class="reference internal" href="#default-contexts">Default Contexts</a></li>
<li><a class="reference internal" href="#exceptional-conditions">Exceptional Conditions</a></li>
<li><a class="reference internal" href="#rounding-algorithms">Rounding Algorithms</a></li>
</ul>
</li>
<li><a class="reference internal" href="#rationale">Rationale</a><ul>
<li><a class="reference internal" href="#explicit-construction">Explicit construction</a><ul>
<li><a class="reference internal" href="#from-int-or-long">From int or long</a></li>
<li><a class="reference internal" href="#from-string">From string</a></li>
<li><a class="reference internal" href="#from-float">From float</a></li>
<li><a class="reference internal" href="#from-tuples">From tuples</a></li>
<li><a class="reference internal" href="#from-decimal">From Decimal</a></li>
<li><a class="reference internal" href="#syntax-for-all-cases">Syntax for All Cases</a></li>
<li><a class="reference internal" href="#creating-from-context">Creating from Context</a></li>
</ul>
</li>
<li><a class="reference internal" href="#implicit-construction">Implicit construction</a><ul>
<li><a class="reference internal" href="#id15">From int or long</a></li>
<li><a class="reference internal" href="#id16">From string</a></li>
<li><a class="reference internal" href="#id17">From float</a></li>
<li><a class="reference internal" href="#id18">From Decimal</a></li>
</ul>
</li>
<li><a class="reference internal" href="#use-of-context">Use of Context</a></li>
<li><a class="reference internal" href="#python-usability">Python Usability</a></li>
</ul>
</li>
<li><a class="reference internal" href="#documentation">Documentation</a><ul>
<li><a class="reference internal" href="#decimal-attributes">Decimal Attributes</a></li>
<li><a class="reference internal" href="#decimal-methods">Decimal Methods</a></li>
<li><a class="reference internal" href="#context-attributes">Context Attributes</a></li>
<li><a class="reference internal" href="#context-methods">Context Methods</a></li>
</ul>
</li>
<li><a class="reference internal" href="#reference-implementation">Reference Implementation</a></li>
<li><a class="reference internal" href="#references">References</a></li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
</ul>
<br>
<a id="source" href="https://github.com/python/peps/blob/main/peps/pep-0327.rst">Page Source (GitHub)</a>
</nav>
</section>
<script src="../_static/colour_scheme.js"></script>
<script src="../_static/wrap_tables.js"></script>
<script src="../_static/sticky_banner.js"></script>
</body>
</html>