CINXE.COM
PEP 228 – Reworking Python’s Numeric Model | peps.python.org
<!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 228 – Reworking Python’s Numeric Model | peps.python.org</title> <link rel="shortcut icon" href="../_static/py.png"> <link rel="canonical" href="https://peps.python.org/pep-0228/"> <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 228 – Reworking Python’s Numeric Model | peps.python.org'> <meta property="og:description" content="Today, Python’s numerical model is similar to the C numeric model: there are several unrelated numerical types, and when operations between numerical types are requested, coercions happen. While the C rationale for the numerical model is that it is ver..."> <meta property="og:type" content="website"> <meta property="og:url" content="https://peps.python.org/pep-0228/"> <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="Today, Python’s numerical model is similar to the C numeric model: there are several unrelated numerical types, and when operations between numerical types are requested, coercions happen. While the C rationale for the numerical model is that it is ver..."> <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> » </li> <li><a href="../pep-0000/">PEP Index</a> » </li> <li>PEP 228</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 228 – Reworking Python’s Numeric Model</h1> <dl class="rfc2822 field-list simple"> <dt class="field-odd">Author<span class="colon">:</span></dt> <dd class="field-odd">Moshe Zadka <moshez at zadka.site.co.il>, Guido van Rossum <guido at python.org></dd> <dt class="field-even">Status<span class="colon">:</span></dt> <dd class="field-even"><abbr title="Removed from consideration by sponsor or authors">Withdrawn</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">04-Nov-2000</dd> <dt class="field-odd">Post-History<span class="colon">:</span></dt> <dd class="field-odd"><p></p></dd> </dl> <hr class="docutils" /> <section id="contents"> <details><summary>Table of Contents</summary><ul class="simple"> <li><a class="reference internal" href="#withdrawal">Withdrawal</a></li> <li><a class="reference internal" href="#abstract">Abstract</a></li> <li><a class="reference internal" href="#rationale">Rationale</a></li> <li><a class="reference internal" href="#other-numerical-models">Other Numerical Models</a></li> <li><a class="reference internal" href="#suggested-interface-for-python-s-numerical-model">Suggested Interface For Python’s Numerical Model</a></li> <li><a class="reference internal" href="#coercion">Coercion</a></li> <li><a class="reference internal" href="#inexact-operations">Inexact Operations</a></li> <li><a class="reference internal" href="#numerical-python-issues">Numerical Python Issues</a></li> <li><a class="reference internal" href="#unresolved-issues">Unresolved Issues</a></li> <li><a class="reference internal" href="#copyright">Copyright</a></li> </ul> </details></section> <section id="withdrawal"> <h2><a class="toc-backref" href="#withdrawal" role="doc-backlink">Withdrawal</a></h2> <p>This PEP has been withdrawn in favor of <a class="pep reference internal" href="../pep-3141/" title="PEP 3141 – A Type Hierarchy for Numbers">PEP 3141</a>.</p> </section> <section id="abstract"> <h2><a class="toc-backref" href="#abstract" role="doc-backlink">Abstract</a></h2> <p>Today, Python’s numerical model is similar to the C numeric model: there are several unrelated numerical types, and when operations between numerical types are requested, coercions happen. While the C rationale for the numerical model is that it is very similar to what happens at the hardware level, that rationale does not apply to Python. So, while it is acceptable to C programmers that <code class="docutils literal notranslate"><span class="pre">2/3</span> <span class="pre">==</span> <span class="pre">0</span></code>, it is surprising to many Python programmers.</p> <p>NOTE: in the light of recent discussions in the newsgroup, the motivation in this PEP (and details) need to be extended.</p> </section> <section id="rationale"> <h2><a class="toc-backref" href="#rationale" role="doc-backlink">Rationale</a></h2> <p>In usability studies, one of the least usable aspect of Python was the fact that integer division returns the floor of the division. This makes it hard to program correctly, requiring casts to <code class="docutils literal notranslate"><span class="pre">float()</span></code> in various parts through the code. Python’s numerical model stems from C, while a model that might be easier to work with can be based on the mathematical understanding of numbers.</p> </section> <section id="other-numerical-models"> <h2><a class="toc-backref" href="#other-numerical-models" role="doc-backlink">Other Numerical Models</a></h2> <p>Perl’s numerical model is that there is one type of numbers – floating point numbers. While it is consistent and superficially non-surprising, it tends to have subtle gotchas. One of these is that printing numbers is very tricky, and requires correct rounding. In Perl, there is also a mode where all numbers are integers. This mode also has its share of problems, which arise from the fact that there is not even an approximate way of dividing numbers and getting meaningful answers.</p> </section> <section id="suggested-interface-for-python-s-numerical-model"> <h2><a class="toc-backref" href="#suggested-interface-for-python-s-numerical-model" role="doc-backlink">Suggested Interface For Python’s Numerical Model</a></h2> <p>While coercion rules will remain for add-on types and classes, the built in type system will have exactly one Python type – a number. There are several things which can be considered “number methods”:</p> <ol class="arabic simple"> <li><code class="docutils literal notranslate"><span class="pre">isnatural()</span></code></li> <li><code class="docutils literal notranslate"><span class="pre">isintegral()</span></code></li> <li><code class="docutils literal notranslate"><span class="pre">isrational()</span></code></li> <li><code class="docutils literal notranslate"><span class="pre">isreal()</span></code></li> <li><code class="docutils literal notranslate"><span class="pre">iscomplex()</span></code></li> <li><code class="docutils literal notranslate"><span class="pre">isexact()</span></code></li> </ol> <p>Obviously, a number which answers true to a question from 1 to 5, will also answer true to any following question. If <code class="docutils literal notranslate"><span class="pre">isexact()</span></code> is not true, then any answer might be wrong. (But not horribly wrong: it’s close to the truth.)</p> <p>Now, there is two thing the models promises for the field operations (<code class="docutils literal notranslate"><span class="pre">+</span></code>, <code class="docutils literal notranslate"><span class="pre">-</span></code>, <code class="docutils literal notranslate"><span class="pre">/</span></code>, <code class="docutils literal notranslate"><span class="pre">*</span></code>):</p> <ul class="simple"> <li>If both operands satisfy <code class="docutils literal notranslate"><span class="pre">isexact()</span></code>, the result satisfies <code class="docutils literal notranslate"><span class="pre">isexact()</span></code>.</li> <li>All field rules are true, except that for not-<code class="docutils literal notranslate"><span class="pre">isexact()</span></code> numbers, they might be only approximately true.</li> </ul> <p>One consequence of these two rules is that all exact calculations are done as (complex) rationals: since the field laws must hold, then</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">(</span><span class="n">a</span><span class="o">/</span><span class="n">b</span><span class="p">)</span><span class="o">*</span><span class="n">b</span> <span class="o">==</span> <span class="n">a</span> </pre></div> </div> <p>must hold.</p> <p>There is built-in function, <code class="docutils literal notranslate"><span class="pre">inexact()</span></code> which takes a number and returns an inexact number which is a good approximation. Inexact numbers must be as least as accurate as if they were using IEEE-754.</p> <p>Several of the classical Python functions will return exact numbers even when given inexact numbers: e.g, <code class="docutils literal notranslate"><span class="pre">int()</span></code>.</p> </section> <section id="coercion"> <h2><a class="toc-backref" href="#coercion" role="doc-backlink">Coercion</a></h2> <p>The number type does not define <code class="docutils literal notranslate"><span class="pre">nb_coerce</span></code> Any numeric operation slot, when receiving something other then <code class="docutils literal notranslate"><span class="pre">PyNumber</span></code>, refuses to implement it.</p> </section> <section id="inexact-operations"> <h2><a class="toc-backref" href="#inexact-operations" role="doc-backlink">Inexact Operations</a></h2> <p>The functions in the <code class="docutils literal notranslate"><span class="pre">math</span></code> module will be allowed to return inexact results for exact values. However, they will never return a non-real number. The functions in the <code class="docutils literal notranslate"><span class="pre">cmath</span></code> module are also allowed to return an inexact result for an exact argument, and are furthermore allowed to return a complex result for a real argument.</p> </section> <section id="numerical-python-issues"> <h2><a class="toc-backref" href="#numerical-python-issues" role="doc-backlink">Numerical Python Issues</a></h2> <p>People who use Numerical Python do so for high-performance vector operations. Therefore, NumPy should keep its hardware based numeric model.</p> </section> <section id="unresolved-issues"> <h2><a class="toc-backref" href="#unresolved-issues" role="doc-backlink">Unresolved Issues</a></h2> <p>Which number literals will be exact, and which inexact?</p> <p>How do we deal with IEEE 754 operations? (probably, isnan/isinf should be methods)</p> <p>On 64-bit machines, comparisons between ints and floats may be broken when the comparison involves conversion to float. Ditto for comparisons between longs and floats. This can be dealt with by avoiding the conversion to float. (Due to Andrew Koenig.)</p> </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-0228.rst">https://github.com/python/peps/blob/main/peps/pep-0228.rst</a></p> <p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0228.rst">2025-02-01 08:55:40 GMT</a></p> </article> <nav id="pep-sidebar"> <h2>Contents</h2> <ul> <li><a class="reference internal" href="#withdrawal">Withdrawal</a></li> <li><a class="reference internal" href="#abstract">Abstract</a></li> <li><a class="reference internal" href="#rationale">Rationale</a></li> <li><a class="reference internal" href="#other-numerical-models">Other Numerical Models</a></li> <li><a class="reference internal" href="#suggested-interface-for-python-s-numerical-model">Suggested Interface For Python’s Numerical Model</a></li> <li><a class="reference internal" href="#coercion">Coercion</a></li> <li><a class="reference internal" href="#inexact-operations">Inexact Operations</a></li> <li><a class="reference internal" href="#numerical-python-issues">Numerical Python Issues</a></li> <li><a class="reference internal" href="#unresolved-issues">Unresolved Issues</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-0228.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>