Index: Include/floatobject.h =================================================================== --- Include/floatobject.h (revision 83218) +++ Include/floatobject.h (working copy) @@ -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 Index: Objects/complexobject.c =================================================================== --- Objects/complexobject.c (revision 83218) +++ Objects/complexobject.c (working copy) @@ -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 */ Index: Objects/stringlib/formatter.h =================================================================== --- Objects/stringlib/formatter.h (revision 83218) +++ Objects/stringlib/formatter.h (working copy) @@ -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; add_parens = 1; if (re == 0.0) skip_re = 1; @@ -1148,6 +1151,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" Index: Objects/floatobject.c =================================================================== --- Objects/floatobject.c (revision 83218) +++ Objects/floatobject.c (working copy) @@ -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 */ Index: Doc/tutorial/floatingpoint.rst =================================================================== --- Doc/tutorial/floatingpoint.rst (revision 83224) +++ Doc/tutorial/floatingpoint.rst (working copy) @@ -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. Index: Lib/test/test_tokenize.py =================================================================== --- Lib/test/test_tokenize.py (revision 83218) +++ Lib/test/test_tokenize.py (working copy) @@ -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. Index: Lib/test/formatfloat_testcases.txt =================================================================== --- Lib/test/formatfloat_testcases.txt (revision 83218) +++ Lib/test/formatfloat_testcases.txt (working copy) @@ -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 +%r 0 -> 0.0 +%r 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 +%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 --- str truncates to 12 significant digits -%s 1.234123412341 -> 1.23412341234 -%s 1.23412341234 -> 1.23412341234 -%s 1.2341234123 -> 1.2341234123 +-- 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 --- 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 - -- 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 Index: Lib/test/test_float.py =================================================================== --- Lib/test/test_float.py (revision 83218) +++ Lib/test/test_float.py (working copy) @@ -617,8 +617,10 @@ 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): Index: Lib/test/test_unicodedata.py =================================================================== --- Lib/test/test_unicodedata.py (revision 83218) +++ Lib/test/test_unicodedata.py (working copy) @@ -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),