Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 388122d

Browse files
committed
Issue #9337: Make float.__str__ identical to float.__repr__.
(And similarly for complex numbers.)
1 parent b6c5074 commit 388122d

10 files changed

Lines changed: 63 additions & 85 deletions

File tree

Doc/tutorial/floatingpoint.rst

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -92,18 +92,17 @@ thing in all languages that support your hardware's floating-point arithmetic
9292
(although some languages may not *display* the difference by default, or in all
9393
output modes).
9494

95-
Python's built-in :func:`str` function produces only 12 significant digits, and
96-
you may wish to use that instead. It's unusual for ``eval(str(x))`` to
97-
reproduce *x*, but the output may be more pleasant to look at::
95+
For more pleasant output, you may may wish to use string formatting to produce a limited number of significant digits::
9896

99-
>>> str(math.pi)
97+
>>> format(math.pi, '.12g') # give 12 significant digits
10098
'3.14159265359'
10199

100+
>>> format(math.pi, '.2f') # give 2 digits after the point
101+
'3.14'
102+
102103
>>> repr(math.pi)
103104
'3.141592653589793'
104105

105-
>>> format(math.pi, '.2f')
106-
'3.14'
107106

108107
It's important to realize that this is, in a real sense, an illusion: you're
109108
simply rounding the *display* of the true machine value.

Include/floatobject.h

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,6 @@ PyAPI_DATA(PyTypeObject) PyFloat_Type;
2121
#define PyFloat_Check(op) PyObject_TypeCheck(op, &PyFloat_Type)
2222
#define PyFloat_CheckExact(op) (Py_TYPE(op) == &PyFloat_Type)
2323

24-
/* The str() precision PyFloat_STR_PRECISION is chosen so that in most cases,
25-
the rounding noise created by various operations is suppressed, while
26-
giving plenty of precision for practical use. */
27-
28-
#define PyFloat_STR_PRECISION 12
29-
3024
#ifdef Py_NAN
3125
#define Py_RETURN_NAN return PyFloat_FromDouble(Py_NAN)
3226
#endif

Lib/test/formatfloat_testcases.txt

Lines changed: 29 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -314,43 +314,37 @@
314314
%#.5g 234.56 -> 234.56
315315
%#.6g 234.56 -> 234.560
316316

317-
-- for repr formatting see the separate test_short_repr test in
318-
-- test_float.py. Not all platforms use short repr for floats.
319-
320-
-- str formatting. Result always includes decimal point and at
317+
-- repr formatting. Result always includes decimal point and at
321318
-- least one digit after the point, or an exponent.
322-
%s 0 -> 0.0
323-
%s 1 -> 1.0
324-
325-
%s 0.01 -> 0.01
326-
%s 0.02 -> 0.02
327-
%s 0.03 -> 0.03
328-
%s 0.04 -> 0.04
329-
%s 0.05 -> 0.05
319+
%r 0 -> 0.0
320+
%r 1 -> 1.0
330321

331-
-- str truncates to 12 significant digits
332-
%s 1.234123412341 -> 1.23412341234
333-
%s 1.23412341234 -> 1.23412341234
334-
%s 1.2341234123 -> 1.2341234123
322+
%r 0.01 -> 0.01
323+
%r 0.02 -> 0.02
324+
%r 0.03 -> 0.03
325+
%r 0.04 -> 0.04
326+
%r 0.05 -> 0.05
335327

336-
-- values >= 1e11 get an exponent
337-
%s 10 -> 10.0
338-
%s 100 -> 100.0
339-
%s 1e10 -> 10000000000.0
340-
%s 9.999e10 -> 99990000000.0
341-
%s 99999999999 -> 99999999999.0
342-
%s 99999999999.9 -> 99999999999.9
343-
%s 99999999999.99 -> 1e+11
344-
%s 1e11 -> 1e+11
345-
%s 1e12 -> 1e+12
328+
-- values >= 1e16 get an exponent
329+
%r 10 -> 10.0
330+
%r 100 -> 100.0
331+
%r 1e15 -> 1000000000000000.0
332+
%r 9.999e15 -> 9999000000000000.0
333+
%r 9999999999999998 -> 9999999999999998.0
334+
%r 9999999999999999 -> 1e+16
335+
%r 1e16 -> 1e+16
336+
%r 1e17 -> 1e+17
346337

347338
-- as do values < 1e-4
348-
%s 1e-3 -> 0.001
349-
%s 1.001e-4 -> 0.0001001
350-
%s 1.000000000001e-4 -> 0.0001
351-
%s 1.00000000001e-4 -> 0.000100000000001
352-
%s 1.0000000001e-4 -> 0.00010000000001
353-
%s 1e-4 -> 0.0001
354-
%s 0.999999999999e-4 -> 9.99999999999e-05
355-
%s 0.999e-4 -> 9.99e-05
356-
%s 1e-5 -> 1e-05
339+
%r 1e-3 -> 0.001
340+
%r 1.001e-4 -> 0.0001001
341+
%r 1.0000000000000001e-4 -> 0.0001
342+
%r 1.000000000000001e-4 -> 0.0001000000000000001
343+
%r 1.00000000001e-4 -> 0.000100000000001
344+
%r 1.0000000001e-4 -> 0.00010000000001
345+
%r 1e-4 -> 0.0001
346+
%r 0.99999999999999999e-4 -> 0.0001
347+
%r 0.9999999999999999e-4 -> 9.999999999999999e-05
348+
%r 0.999999999999e-4 -> 9.99999999999e-05
349+
%r 0.999e-4 -> 9.99e-05
350+
%r 1e-5 -> 1e-05

Lib/test/test_float.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -617,7 +617,9 @@ def test_short_repr(self):
617617
negs = '-'+s
618618
self.assertEqual(s, repr(float(s)))
619619
self.assertEqual(negs, repr(float(negs)))
620-
620+
# Since Python 3.2, repr and str are identical
621+
self.assertEqual(repr(float(s)), str(float(s)))
622+
self.assertEqual(repr(float(negs)), str(float(negs)))
621623

622624
@requires_IEEE_754
623625
class RoundTestCase(unittest.TestCase):

Lib/test/test_tokenize.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -598,11 +598,11 @@ def decistmt(s):
598598
599599
The format of the exponent is inherited from the platform C library.
600600
Known cases are "e-007" (Windows) and "e-07" (not Windows). Since
601-
we're only showing 12 digits, and the 13th isn't close to 5, the
601+
we're only showing 11 digits, and the 12th isn't close to 5, the
602602
rest of the output should be platform-independent.
603603
604604
>>> exec(s) #doctest: +ELLIPSIS
605-
-3.21716034272e-0...7
605+
-3.2171603427...e-0...7
606606
607607
Output from calculations with Decimal should be identical across all
608608
platforms.

Lib/test/test_unicodedata.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,7 @@ def tearDown(self):
8080
class UnicodeFunctionsTest(UnicodeDatabaseTest):
8181

8282
# update this, if the database changes
83-
expectedchecksum = '6ccf1b1a36460d2694f9b0b0f0324942fe70ede6'
84-
83+
expectedchecksum = 'e89a6380093a00a7685ac7b92e7367d737fcb79b'
8584
def test_function_checksum(self):
8685
data = []
8786
h = hashlib.sha1()
@@ -90,9 +89,9 @@ def test_function_checksum(self):
9089
char = chr(i)
9190
data = [
9291
# Properties
93-
str(self.db.digit(char, -1)),
94-
str(self.db.numeric(char, -1)),
95-
str(self.db.decimal(char, -1)),
92+
format(self.db.digit(char, -1), '.12g'),
93+
format(self.db.numeric(char, -1), '.12g'),
94+
format(self.db.decimal(char, -1), '.12g'),
9695
self.db.category(char),
9796
self.db.bidirectional(char),
9897
self.db.decomposition(char),

Misc/NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ What's New in Python 3.2 Alpha 2?
1212
Core and Builtins
1313
-----------------
1414

15+
- Issue #9337: The str() of a float or complex number is now identical
16+
to its repr().
17+
1518
- Issue #9416: Fix some issues with complex formatting where the
1619
output with no type specifier failed to match the str output:
1720

Objects/complexobject.c

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -394,12 +394,6 @@ complex_repr(PyComplexObject *v)
394394
return complex_format(v, 0, 'r');
395395
}
396396

397-
static PyObject *
398-
complex_str(PyComplexObject *v)
399-
{
400-
return complex_format(v, PyFloat_STR_PRECISION, 'g');
401-
}
402-
403397
static long
404398
complex_hash(PyComplexObject *v)
405399
{
@@ -1104,7 +1098,7 @@ PyTypeObject PyComplex_Type = {
11041098
0, /* tp_as_mapping */
11051099
(hashfunc)complex_hash, /* tp_hash */
11061100
0, /* tp_call */
1107-
(reprfunc)complex_str, /* tp_str */
1101+
(reprfunc)complex_repr, /* tp_str */
11081102
PyObject_GenericGetAttr, /* tp_getattro */
11091103
0, /* tp_setattro */
11101104
0, /* tp_as_buffer */

Objects/floatobject.c

Lines changed: 5 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -305,32 +305,20 @@ convert_to_double(PyObject **v, double *dbl)
305305
}
306306

307307
static PyObject *
308-
float_str_or_repr(PyFloatObject *v, int precision, char format_code)
308+
float_repr(PyFloatObject *v)
309309
{
310310
PyObject *result;
311311
char *buf = PyOS_double_to_string(PyFloat_AS_DOUBLE(v),
312-
format_code, precision,
312+
'r', 0,
313313
Py_DTSF_ADD_DOT_0,
314314
NULL);
315315
if (!buf)
316-
return PyErr_NoMemory();
316+
return PyErr_NoMemory();
317317
result = PyUnicode_FromString(buf);
318318
PyMem_Free(buf);
319319
return result;
320320
}
321321

322-
static PyObject *
323-
float_repr(PyFloatObject *v)
324-
{
325-
return float_str_or_repr(v, 0, 'r');
326-
}
327-
328-
static PyObject *
329-
float_str(PyFloatObject *v)
330-
{
331-
return float_str_or_repr(v, PyFloat_STR_PRECISION, 'g');
332-
}
333-
334322
/* Comparison is pretty much a nightmare. When comparing float to float,
335323
* we do it as straightforwardly (and long-windedly) as conceivable, so
336324
* that, e.g., Python x == y delivers the same result as the platform
@@ -1169,7 +1157,7 @@ float_hex(PyObject *v)
11691157
CONVERT_TO_DOUBLE(v, x);
11701158

11711159
if (Py_IS_NAN(x) || Py_IS_INFINITY(x))
1172-
return float_str((PyFloatObject *)v);
1160+
return float_repr((PyFloatObject *)v);
11731161

11741162
if (x == 0.0) {
11751163
if (copysign(1.0, x) == -1.0)
@@ -1873,7 +1861,7 @@ PyTypeObject PyFloat_Type = {
18731861
0, /* tp_as_mapping */
18741862
(hashfunc)float_hash, /* tp_hash */
18751863
0, /* tp_call */
1876-
(reprfunc)float_str, /* tp_str */
1864+
(reprfunc)float_repr, /* tp_str */
18771865
PyObject_GenericGetAttr, /* tp_getattro */
18781866
0, /* tp_setattro */
18791867
0, /* tp_as_buffer */

Objects/stringlib/formatter.h

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -950,11 +950,12 @@ format_float_internal(PyObject *value,
950950
}
951951

952952
if (type == '\0') {
953-
/* Omitted type specifier. This is like 'g' but with at least one
954-
digit after the decimal point, and different default precision.*/
955-
type = 'g';
956-
default_precision = PyFloat_STR_PRECISION;
953+
/* Omitted type specifier. Behaves in the same way as repr(x)
954+
and str(x) if no precision is given, else like 'g', but with
955+
at least one digit after the decimal point. */
957956
flags |= Py_DTSF_ADD_DOT_0;
957+
type = 'r';
958+
default_precision = 0;
958959
}
959960

960961
if (type == 'n')
@@ -974,6 +975,8 @@ format_float_internal(PyObject *value,
974975

975976
if (precision < 0)
976977
precision = default_precision;
978+
else if (type == 'r')
979+
type = 'g';
977980

978981
/* Cast "type", because if we're in unicode we need to pass a
979982
8-bit char. This is safe, because we've restricted what "type"
@@ -1134,8 +1137,8 @@ format_complex_internal(PyObject *value,
11341137

11351138
if (type == '\0') {
11361139
/* Omitted type specifier. Should be like str(self). */
1137-
type = 'g';
1138-
default_precision = PyFloat_STR_PRECISION;
1140+
type = 'r';
1141+
default_precision = 0;
11391142
if (re == 0.0 && copysign(1.0, re) == 1.0)
11401143
skip_re = 1;
11411144
else
@@ -1149,6 +1152,8 @@ format_complex_internal(PyObject *value,
11491152

11501153
if (precision < 0)
11511154
precision = default_precision;
1155+
else if (type == 'r')
1156+
type = 'g';
11521157

11531158
/* Cast "type", because if we're in unicode we need to pass a
11541159
8-bit char. This is safe, because we've restricted what "type"

0 commit comments

Comments
 (0)