[Python-checkins] r83736 - in python/branches/py3k: Doc/tutorial/floatingpoint.rst Include/floatobject.h Lib/test/formatfloat_testcases.txt Lib/test/test_float.py Lib/test/test_tokenize.py Lib/test/test_unicodedata.py Misc/NEWS Objects/complexobject.c Objects/floatobject.c Objects/stringlib/formatter.h

mark.dickinson python-checkins at python.org
Wed Aug 4 22:56:28 CEST 2010


Author: mark.dickinson
Date: Wed Aug  4 22:56:28 2010
New Revision: 83736

Log:
Issue #9337:  Make float.__str__ identical to float.__repr__.
(And similarly for complex numbers.)


Modified:
   python/branches/py3k/Doc/tutorial/floatingpoint.rst
   python/branches/py3k/Include/floatobject.h
   python/branches/py3k/Lib/test/formatfloat_testcases.txt
   python/branches/py3k/Lib/test/test_float.py
   python/branches/py3k/Lib/test/test_tokenize.py
   python/branches/py3k/Lib/test/test_unicodedata.py
   python/branches/py3k/Misc/NEWS
   python/branches/py3k/Objects/complexobject.c
   python/branches/py3k/Objects/floatobject.c
   python/branches/py3k/Objects/stringlib/formatter.h

Modified: python/branches/py3k/Doc/tutorial/floatingpoint.rst
==============================================================================
--- python/branches/py3k/Doc/tutorial/floatingpoint.rst	(original)
+++ python/branches/py3k/Doc/tutorial/floatingpoint.rst	Wed Aug  4 22:56:28 2010
@@ -92,18 +92,17 @@
 (although some languages may not *display* the difference by default, or in all
 output modes).
 
-Python's built-in :func:`str` function produces only 12 significant digits, and
-you may wish to use that instead.  It's unusual for ``eval(str(x))`` to
-reproduce *x*, but the output may be more pleasant to look at::
+For more pleasant output, you may may wish to use string formatting to produce a limited number of significant digits::
 
-   >>> str(math.pi)
+   >>> format(math.pi, '.12g')  # give 12 significant digits
    '3.14159265359'
 
+   >>> format(math.pi, '.2f')   # give 2 digits after the point
+   '3.14'
+
    >>> repr(math.pi)
    '3.141592653589793'
 
-   >>> format(math.pi, '.2f')
-   '3.14'
 
 It's important to realize that this is, in a real sense, an illusion: you're
 simply rounding the *display* of the true machine value.

Modified: python/branches/py3k/Include/floatobject.h
==============================================================================
--- python/branches/py3k/Include/floatobject.h	(original)
+++ python/branches/py3k/Include/floatobject.h	Wed Aug  4 22:56:28 2010
@@ -21,12 +21,6 @@
 #define PyFloat_Check(op) PyObject_TypeCheck(op, &PyFloat_Type)
 #define PyFloat_CheckExact(op) (Py_TYPE(op) == &PyFloat_Type)
 
-/* The str() precision PyFloat_STR_PRECISION is chosen so that in most cases,
-   the rounding noise created by various operations is suppressed, while
-   giving plenty of precision for practical use. */
-
-#define PyFloat_STR_PRECISION 12
-
 #ifdef Py_NAN
 #define Py_RETURN_NAN return PyFloat_FromDouble(Py_NAN)
 #endif

Modified: python/branches/py3k/Lib/test/formatfloat_testcases.txt
==============================================================================
--- python/branches/py3k/Lib/test/formatfloat_testcases.txt	(original)
+++ python/branches/py3k/Lib/test/formatfloat_testcases.txt	Wed Aug  4 22:56:28 2010
@@ -314,43 +314,37 @@
 %#.5g 234.56 -> 234.56
 %#.6g 234.56 -> 234.560
 
--- for repr formatting see the separate test_short_repr test in
--- test_float.py.  Not all platforms use short repr for floats.
-
--- str formatting.  Result always includes decimal point and at
+-- repr formatting.  Result always includes decimal point and at
 -- least one digit after the point, or an exponent.
-%s 0 -> 0.0
-%s 1 -> 1.0
-
-%s 0.01 -> 0.01
-%s 0.02 -> 0.02
-%s 0.03 -> 0.03
-%s 0.04 -> 0.04
-%s 0.05 -> 0.05
-
--- str truncates to 12 significant digits
-%s 1.234123412341 -> 1.23412341234
-%s 1.23412341234 -> 1.23412341234
-%s 1.2341234123 -> 1.2341234123
+%r 0 -> 0.0
+%r 1 -> 1.0
 
--- values >= 1e11 get an exponent
-%s 10 -> 10.0
-%s 100 -> 100.0
-%s 1e10 -> 10000000000.0
-%s 9.999e10 -> 99990000000.0
-%s 99999999999 -> 99999999999.0
-%s 99999999999.9 -> 99999999999.9
-%s 99999999999.99 -> 1e+11
-%s 1e11 -> 1e+11
-%s 1e12 -> 1e+12
+%r 0.01 -> 0.01
+%r 0.02 -> 0.02
+%r 0.03 -> 0.03
+%r 0.04 -> 0.04
+%r 0.05 -> 0.05
+
+-- values >= 1e16 get an exponent
+%r 10 -> 10.0
+%r 100 -> 100.0
+%r 1e15 -> 1000000000000000.0
+%r 9.999e15 -> 9999000000000000.0
+%r 9999999999999998 -> 9999999999999998.0
+%r 9999999999999999 -> 1e+16
+%r 1e16 -> 1e+16
+%r 1e17 -> 1e+17
 
 -- as do values < 1e-4
-%s 1e-3 -> 0.001
-%s 1.001e-4 -> 0.0001001
-%s 1.000000000001e-4 -> 0.0001
-%s 1.00000000001e-4 -> 0.000100000000001
-%s 1.0000000001e-4 -> 0.00010000000001
-%s 1e-4 -> 0.0001
-%s 0.999999999999e-4 -> 9.99999999999e-05
-%s 0.999e-4 -> 9.99e-05
-%s 1e-5 -> 1e-05
+%r 1e-3 -> 0.001
+%r 1.001e-4 -> 0.0001001
+%r 1.0000000000000001e-4 -> 0.0001
+%r 1.000000000000001e-4 -> 0.0001000000000000001
+%r 1.00000000001e-4 -> 0.000100000000001
+%r 1.0000000001e-4 -> 0.00010000000001
+%r 1e-4 -> 0.0001
+%r 0.99999999999999999e-4 -> 0.0001
+%r 0.9999999999999999e-4 -> 9.999999999999999e-05
+%r 0.999999999999e-4 -> 9.99999999999e-05
+%r 0.999e-4 -> 9.99e-05
+%r 1e-5 -> 1e-05

Modified: python/branches/py3k/Lib/test/test_float.py
==============================================================================
--- python/branches/py3k/Lib/test/test_float.py	(original)
+++ python/branches/py3k/Lib/test/test_float.py	Wed Aug  4 22:56:28 2010
@@ -617,7 +617,9 @@
             negs = '-'+s
             self.assertEqual(s, repr(float(s)))
             self.assertEqual(negs, repr(float(negs)))
-
+            # Since Python 3.2, repr and str are identical
+            self.assertEqual(repr(float(s)), str(float(s)))
+            self.assertEqual(repr(float(negs)), str(float(negs)))
 
 @requires_IEEE_754
 class RoundTestCase(unittest.TestCase):

Modified: python/branches/py3k/Lib/test/test_tokenize.py
==============================================================================
--- python/branches/py3k/Lib/test/test_tokenize.py	(original)
+++ python/branches/py3k/Lib/test/test_tokenize.py	Wed Aug  4 22:56:28 2010
@@ -598,11 +598,11 @@
 
     The format of the exponent is inherited from the platform C library.
     Known cases are "e-007" (Windows) and "e-07" (not Windows).  Since
-    we're only showing 12 digits, and the 13th isn't close to 5, the
+    we're only showing 11 digits, and the 12th isn't close to 5, the
     rest of the output should be platform-independent.
 
     >>> exec(s) #doctest: +ELLIPSIS
-    -3.21716034272e-0...7
+    -3.2171603427...e-0...7
 
     Output from calculations with Decimal should be identical across all
     platforms.

Modified: python/branches/py3k/Lib/test/test_unicodedata.py
==============================================================================
--- python/branches/py3k/Lib/test/test_unicodedata.py	(original)
+++ python/branches/py3k/Lib/test/test_unicodedata.py	Wed Aug  4 22:56:28 2010
@@ -80,8 +80,7 @@
 class UnicodeFunctionsTest(UnicodeDatabaseTest):
 
     # update this, if the database changes
-    expectedchecksum = '6ccf1b1a36460d2694f9b0b0f0324942fe70ede6'
-
+    expectedchecksum = 'e89a6380093a00a7685ac7b92e7367d737fcb79b'
     def test_function_checksum(self):
         data = []
         h = hashlib.sha1()
@@ -90,9 +89,9 @@
             char = chr(i)
             data = [
                 # Properties
-                str(self.db.digit(char, -1)),
-                str(self.db.numeric(char, -1)),
-                str(self.db.decimal(char, -1)),
+                format(self.db.digit(char, -1), '.12g'),
+                format(self.db.numeric(char, -1), '.12g'),
+                format(self.db.decimal(char, -1), '.12g'),
                 self.db.category(char),
                 self.db.bidirectional(char),
                 self.db.decomposition(char),

Modified: python/branches/py3k/Misc/NEWS
==============================================================================
--- python/branches/py3k/Misc/NEWS	(original)
+++ python/branches/py3k/Misc/NEWS	Wed Aug  4 22:56:28 2010
@@ -12,6 +12,9 @@
 Core and Builtins
 -----------------
 
+- Issue #9337: The str() of a float or complex number is now identical
+  to its repr().
+
 - Issue #9416: Fix some issues with complex formatting where the
   output with no type specifier failed to match the str output:
 

Modified: python/branches/py3k/Objects/complexobject.c
==============================================================================
--- python/branches/py3k/Objects/complexobject.c	(original)
+++ python/branches/py3k/Objects/complexobject.c	Wed Aug  4 22:56:28 2010
@@ -394,12 +394,6 @@
     return complex_format(v, 0, 'r');
 }
 
-static PyObject *
-complex_str(PyComplexObject *v)
-{
-    return complex_format(v, PyFloat_STR_PRECISION, 'g');
-}
-
 static long
 complex_hash(PyComplexObject *v)
 {
@@ -1104,7 +1098,7 @@
     0,                                          /* tp_as_mapping */
     (hashfunc)complex_hash,                     /* tp_hash */
     0,                                          /* tp_call */
-    (reprfunc)complex_str,                      /* tp_str */
+    (reprfunc)complex_repr,                     /* tp_str */
     PyObject_GenericGetAttr,                    /* tp_getattro */
     0,                                          /* tp_setattro */
     0,                                          /* tp_as_buffer */

Modified: python/branches/py3k/Objects/floatobject.c
==============================================================================
--- python/branches/py3k/Objects/floatobject.c	(original)
+++ python/branches/py3k/Objects/floatobject.c	Wed Aug  4 22:56:28 2010
@@ -305,32 +305,20 @@
 }
 
 static PyObject *
-float_str_or_repr(PyFloatObject *v, int precision, char format_code)
+float_repr(PyFloatObject *v)
 {
     PyObject *result;
     char *buf = PyOS_double_to_string(PyFloat_AS_DOUBLE(v),
-                                      format_code, precision,
+                                      'r', 0,
                                       Py_DTSF_ADD_DOT_0,
                                       NULL);
     if (!buf)
-    return PyErr_NoMemory();
+        return PyErr_NoMemory();
     result = PyUnicode_FromString(buf);
     PyMem_Free(buf);
     return result;
 }
 
-static PyObject *
-float_repr(PyFloatObject *v)
-{
-    return float_str_or_repr(v, 0, 'r');
-}
-
-static PyObject *
-float_str(PyFloatObject *v)
-{
-    return float_str_or_repr(v, PyFloat_STR_PRECISION, 'g');
-}
-
 /* Comparison is pretty much a nightmare.  When comparing float to float,
  * we do it as straightforwardly (and long-windedly) as conceivable, so
  * that, e.g., Python x == y delivers the same result as the platform
@@ -1169,7 +1157,7 @@
     CONVERT_TO_DOUBLE(v, x);
 
     if (Py_IS_NAN(x) || Py_IS_INFINITY(x))
-        return float_str((PyFloatObject *)v);
+        return float_repr((PyFloatObject *)v);
 
     if (x == 0.0) {
         if (copysign(1.0, x) == -1.0)
@@ -1873,7 +1861,7 @@
     0,                                          /* tp_as_mapping */
     (hashfunc)float_hash,                       /* tp_hash */
     0,                                          /* tp_call */
-    (reprfunc)float_str,                        /* tp_str */
+    (reprfunc)float_repr,                       /* tp_str */
     PyObject_GenericGetAttr,                    /* tp_getattro */
     0,                                          /* tp_setattro */
     0,                                          /* tp_as_buffer */

Modified: python/branches/py3k/Objects/stringlib/formatter.h
==============================================================================
--- python/branches/py3k/Objects/stringlib/formatter.h	(original)
+++ python/branches/py3k/Objects/stringlib/formatter.h	Wed Aug  4 22:56:28 2010
@@ -950,11 +950,12 @@
     }
 
     if (type == '\0') {
-        /* Omitted type specifier. This is like 'g' but with at least one
-           digit after the decimal point, and different default precision.*/
-        type = 'g';
-        default_precision = PyFloat_STR_PRECISION;
+        /* Omitted type specifier.  Behaves in the same way as repr(x)
+           and str(x) if no precision is given, else like 'g', but with
+           at least one digit after the decimal point. */
         flags |= Py_DTSF_ADD_DOT_0;
+        type = 'r';
+        default_precision = 0;
     }
 
     if (type == 'n')
@@ -974,6 +975,8 @@
 
     if (precision < 0)
         precision = default_precision;
+    else if (type == 'r')
+        type = 'g';
 
     /* Cast "type", because if we're in unicode we need to pass a
        8-bit char. This is safe, because we've restricted what "type"
@@ -1134,8 +1137,8 @@
 
     if (type == '\0') {
         /* Omitted type specifier. Should be like str(self). */
-        type = 'g';
-        default_precision = PyFloat_STR_PRECISION;
+        type = 'r';
+        default_precision = 0;
         if (re == 0.0 && copysign(1.0, re) == 1.0)
             skip_re = 1;
         else
@@ -1149,6 +1152,8 @@
 
     if (precision < 0)
         precision = default_precision;
+    else if (type == 'r')
+        type = 'g';
 
     /* Cast "type", because if we're in unicode we need to pass a
        8-bit char. This is safe, because we've restricted what "type"


More information about the Python-checkins mailing list