Skip to content

Commit 133ea10

Browse files
author
tim_one
committed
SF bug #422177: Results from .pyc differs from .py
Store floats and doubles to full precision in marshal. Test that floats read from .pyc/.pyo closely match those read from .py. Declare PyFloat_AsString() in floatobject header file. Add new PyFloat_AsReprString() API function. Document the functions declared in floatobject.h. git-svn-id: http://svn.python.org/projects/python/trunk@20648 6015fed2-1504-0410-9fe1-9d1591cc4771
1 parent e34eea3 commit 133ea10

4 files changed

Lines changed: 34 additions & 8 deletions

File tree

Include/floatobject.h

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,32 @@ extern DL_IMPORT(PyTypeObject) PyFloat_Type;
2020

2121
#define PyFloat_Check(op) ((op)->ob_type == &PyFloat_Type)
2222

23-
extern DL_IMPORT(PyObject *) PyFloat_FromString(PyObject*, char**);
23+
/* Return Python float from string PyObject. Second argument ignored on
24+
input, and, if non-NULL, NULL is stored into *junk (this tried to serve a
25+
purpose once but can't be made to work as intended). */
26+
extern DL_IMPORT(PyObject *) PyFloat_FromString(PyObject*, char** junk);
27+
28+
/* Return Python float from C double. */
2429
extern DL_IMPORT(PyObject *) PyFloat_FromDouble(double);
25-
extern DL_IMPORT(double) PyFloat_AsDouble(PyObject *);
2630

27-
/* Macro, trading safety for speed */
31+
/* Extract C double from Python float. The macro version trades safety for
32+
speed. */
33+
extern DL_IMPORT(double) PyFloat_AsDouble(PyObject *);
2834
#define PyFloat_AS_DOUBLE(op) (((PyFloatObject *)(op))->ob_fval)
2935

36+
/* Write repr(v) into the char buffer argument, followed by null byte. The
37+
buffer must be "big enough"; >= 100 is very safe.
38+
PyFloat_AsReprString(buf, x) strives to print enough digits so that
39+
PyFloat_FromString(buf) then reproduces x exactly. */
40+
extern DL_IMPORT(void) PyFloat_AsReprString(char*, PyFloatObject *v);
41+
42+
/* Write str(v) into the char buffer argument, followed by null byte. The
43+
buffer must be "big enough"; >= 100 is very safe. Note that it's
44+
unusual to be able to get back the float you started with from
45+
PyFloat_AsString's result -- use PyFloat_AsReprString() if you want to
46+
preserve precision across conversions. */
47+
extern DL_IMPORT(void) PyFloat_AsString(char*, PyFloatObject *v);
48+
3049
#ifdef __cplusplus
3150
}
3251
#endif

Lib/test/test_import.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@
1313
else:
1414
raise TestFailed("import of RAnDoM should have failed (case mismatch)")
1515

16+
# Another brief digression to test the accuracy of manifest float constants.
17+
import double_const # don't blink -- that *was* the test
18+
1619
sys.path.insert(0, os.curdir)
1720

1821
source = TESTFN + ".py"

Objects/floatobject.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,12 @@ PyFloat_AsString(char *buf, PyFloatObject *v)
311311
PyFloat_AsStringEx(buf, v, PREC_STR);
312312
}
313313

314+
void
315+
PyFloat_AsReprString(char *buf, PyFloatObject *v)
316+
{
317+
PyFloat_AsStringEx(buf, v, PREC_REPR);
318+
}
319+
314320
/* ARGSUSED */
315321
static int
316322
float_print(PyFloatObject *v, FILE *fp, int flags)

Python/marshal.c

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -149,30 +149,28 @@ w_object(PyObject *v, WFILE *p)
149149
w_short(ob->ob_digit[i], p);
150150
}
151151
else if (PyFloat_Check(v)) {
152-
extern void PyFloat_AsString(char *, PyFloatObject *);
153152
char buf[256]; /* Plenty to format any double */
154-
PyFloat_AsString(buf, (PyFloatObject *)v);
153+
PyFloat_AsReprString(buf, (PyFloatObject *)v);
155154
n = strlen(buf);
156155
w_byte(TYPE_FLOAT, p);
157156
w_byte(n, p);
158157
w_string(buf, n, p);
159158
}
160159
#ifndef WITHOUT_COMPLEX
161160
else if (PyComplex_Check(v)) {
162-
extern void PyFloat_AsString(char *, PyFloatObject *);
163161
char buf[256]; /* Plenty to format any double */
164162
PyFloatObject *temp;
165163
w_byte(TYPE_COMPLEX, p);
166164
temp = (PyFloatObject*)PyFloat_FromDouble(
167165
PyComplex_RealAsDouble(v));
168-
PyFloat_AsString(buf, temp);
166+
PyFloat_AsReprString(buf, temp);
169167
Py_DECREF(temp);
170168
n = strlen(buf);
171169
w_byte(n, p);
172170
w_string(buf, n, p);
173171
temp = (PyFloatObject*)PyFloat_FromDouble(
174172
PyComplex_ImagAsDouble(v));
175-
PyFloat_AsString(buf, temp);
173+
PyFloat_AsReprString(buf, temp);
176174
Py_DECREF(temp);
177175
n = strlen(buf);
178176
w_byte(n, p);

0 commit comments

Comments
 (0)