Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cpython
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
cpython
Commits
811ff822
Commit
811ff822
authored
Jan 16, 2010
by
Mark Dickinson
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Issue #7632: Fix one more case of incorrect rounding for str -> float
conversion (see bug 5 in the issue tracker).
parent
db983a7c
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
55 additions
and
33 deletions
+55
-33
Lib/test/test_strtod.py
Lib/test/test_strtod.py
+3
-6
Python/dtoa.c
Python/dtoa.c
+52
-27
No files found.
Lib/test/test_strtod.py
View file @
811ff822
...
...
@@ -123,10 +123,6 @@ class StrtodTests(unittest.TestCase):
digits
=
m
*
5
**-
e
exponent
=
e
s
=
'{}e{}'
.
format
(
digits
,
exponent
)
# for the moment, ignore errors from trailing zeros
if
digits
%
10
==
0
:
continue
self
.
check_strtod
(
s
)
# get expected answer via struct, to triple check
...
...
@@ -175,7 +171,8 @@ class StrtodTests(unittest.TestCase):
self
.
check_strtod
(
s
)
def
test_parsing
(
self
):
digits
=
tuple
(
map
(
str
,
xrange
(
10
)))
# make '0' more likely to be chosen than other digits
digits
=
'000000123456789'
signs
=
(
'+'
,
'-'
,
''
)
# put together random short valid strings
...
...
@@ -257,7 +254,7 @@ class StrtodTests(unittest.TestCase):
'247032822920623295e-341'
,
# issue 7632 bug 5: the following 2 strings convert differently
'1000000000000000000000000000000000000000e-16'
,
#
'10000000000000000000000000000000000000000e-17',
'10000000000000000000000000000000000000000e-17'
,
# issue 7632 bug 8: the following produced 10.0
'10.900000000000000012345678912345678912345'
,
]
...
...
Python/dtoa.c
View file @
811ff822
...
...
@@ -1381,12 +1381,8 @@ _Py_dg_strtod(const char *s00, char **se)
goto
ret
;
}
s0
=
s
;
y
=
z
=
0
;
for
(
nd
=
nf
=
0
;
(
c
=
*
s
)
>=
'0'
&&
c
<=
'9'
;
nd
++
,
s
++
)
if
(
nd
<
9
)
y
=
10
*
y
+
c
-
'0'
;
else
if
(
nd
<
16
)
z
=
10
*
z
+
c
-
'0'
;
;
nd0
=
nd
;
if
(
c
==
'.'
)
{
c
=
*++
s
;
...
...
@@ -1406,15 +1402,7 @@ _Py_dg_strtod(const char *s00, char **se)
nz
++
;
if
(
c
-=
'0'
)
{
nf
+=
nz
;
for
(
i
=
1
;
i
<
nz
;
i
++
)
if
(
nd
++
<
9
)
y
*=
10
;
else
if
(
nd
<=
DBL_DIG
+
1
)
z
*=
10
;
if
(
nd
++
<
9
)
y
=
10
*
y
+
c
;
else
if
(
nd
<=
DBL_DIG
+
1
)
z
=
10
*
z
+
c
;
nd
+=
nz
;
nz
=
0
;
}
}
...
...
@@ -1465,32 +1453,59 @@ _Py_dg_strtod(const char *s00, char **se)
}
goto
ret
;
}
bc
.
e0
=
e1
=
e
-=
nf
;
e
-=
nf
;
if
(
!
nd0
)
nd0
=
nd
;
/* strip trailing zeros */
for
(
i
=
nd
;
i
>
0
;
)
{
/* scan back until we hit a nonzero digit. significant digit 'i'
is s0[i] if i < nd0, s0[i+1] if i >= nd0. */
--
i
;
if
(
s0
[
i
<
nd0
?
i
:
i
+
1
]
!=
'0'
)
{
++
i
;
break
;
}
}
e
+=
nd
-
i
;
nd
=
i
;
if
(
nd0
>
nd
)
nd0
=
nd
;
/* Now we have nd0 digits, starting at s0, followed by a
* decimal point, followed by nd-nd0 digits. The number we're
* after is the integer represented by those digits times
* 10**e */
if
(
!
nd0
)
nd0
=
nd
;
bc
.
e0
=
e1
=
e
;
/* Summary of parsing results. The parsing stage gives values
* s0, nd0, nd, e,
y and z such that
:
* s0, nd0, nd, e,
sign, where
:
*
* -
nd >= nd0 >= 1
* -
s0 points to the first significant digit of the input string s00;
*
* - the nd significant digits are in s0[0:nd0] and s0[nd0+1:nd+1]
* (using the usual Python half-open slice notation)
* - nd is the total number of significant digits (here, and
* below, 'significant digits' means the set of digits of the
* significand of the input that remain after ignoring leading
* and trailing zeros.
*
* - the absolute value of the number represented by the original input
* string is n * 10**e, where n is the integer represented by the
* concatenation of s0[0:nd0] and s0[nd0+1:nd+1]
* - nd0 indicates the position of the decimal point (if
* present): so the nd significant digits are in s0[0:nd0] and
* s0[nd0+1:nd+1] using the usual Python half-open slice
* notation. (If nd0 < nd, then s0[nd0] necessarily contains
* a '.' character; if nd0 == nd, then it could be anything.)
*
* - the first significant digit is nonzero
* - e is the adjusted exponent: the absolute value of the number
* represented by the original input string is n * 10**e, where
* n is the integer represented by the concatenation of
* s0[0:nd0] and s0[nd0+1:nd+1]
*
* - the last significant digit may or may not be nonzero; (some code
* currently assumes that it's nonzero; this is a bug)
* - sign gives the sign of the input: 1 for negative, 0 for positive
*
* - the first and last significant digits are nonzero
*/
/* put first DBL_DIG+1 digits into integer y and z.
*
* - y contains the value represented by the first min(9, nd)
* significant digits
...
...
@@ -1500,6 +1515,16 @@ _Py_dg_strtod(const char *s00, char **se)
* gives the value represented by the first min(16, nd) sig. digits.
*/
y
=
z
=
0
;
for
(
i
=
0
;
i
<
nd
;
i
++
)
{
if
(
i
<
9
)
y
=
10
*
y
+
s0
[
i
<
nd0
?
i
:
i
+
1
]
-
'0'
;
else
if
(
i
<
DBL_DIG
+
1
)
z
=
10
*
z
+
s0
[
i
<
nd0
?
i
:
i
+
1
]
-
'0'
;
else
break
;
}
k
=
nd
<
DBL_DIG
+
1
?
nd
:
DBL_DIG
+
1
;
dval
(
&
rv
)
=
y
;
if
(
k
>
9
)
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment