| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent ed44dfa commit 476279f
3 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -258,6 +258,8 @@ def test_particular(self): | |||
| 258 | 258 | # issue 7632 bug 5: the following 2 strings convert differently | |
| 259 | 259 | '1000000000000000000000000000000000000000e-16', | |
| 260 | 260 | #'10000000000000000000000000000000000000000e-17', | |
| 261 | + # issue 7632 bug 8: the following produced 10.0 | ||
| 262 | + '10.900000000000000012345678912345678912345', | ||
| 261 | 263 | ] | |
| 262 | 264 | for s in test_strings: | |
| 263 | 265 | self.check_strtod(s) | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -16,10 +16,12 @@ Core and Builtins | |||
| 16 | 16 | methods of bytes, bytearray and unicode objects by using a common | |
| 17 | 17 | implementation based on stringlib's fast search. Patch by Florent Xicluna. | |
| 18 | 18 | ||
| 19 | - - Issue #7632: Fix a crash in dtoa.c that occurred in debug builds | ||
| 20 | - when parsing certain long numeric strings corresponding to subnormal | ||
| 21 | - values. Also fix a number of bugs in dtoa.c that could lead to | ||
| 22 | - incorrectly rounded results when converting strings to floats. | ||
| 19 | + - Issue #7632: Fix various str -> float conversion bugs present in 2.7 | ||
| 20 | + alpha 2, including: (1) a serious 'wrong output' bug that could | ||
| 21 | + occur for long (> 40 digit) input strings, (2) a crash in dtoa.c | ||
| 22 | + that occurred in debug builds when parsing certain long numeric | ||
| 23 | + strings corresponding to subnormal values, and (3) a number of flaws | ||
| 24 | + that could lead to incorrectly rounded results. | ||
| 23 | 25 | ||
| 24 | 26 | - Issue #7319, #7770: Silence DeprecationWarning by default when -3 is not | |
| 25 | 27 | used. | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1340,7 +1340,7 @@ bigcomp(U *rv, const char *s0, BCinfo *bc) | |||
| 1340 | 1340 | double | |
| 1341 | 1341 | _Py_dg_strtod(const char *s00, char **se) | |
| 1342 | 1342 | { | |
| 1343 | - int bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, dp0, dp1, dplen, e, e1, error; | ||
| 1343 | + int bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, e, e1, error; | ||
| 1344 | 1344 | int esign, i, j, k, nd, nd0, nf, nz, nz0, sign; | |
| 1345 | 1345 | const char *s, *s0, *s1; | |
| 1346 | 1346 | double aadj, aadj1; | |
@@ -1349,7 +1349,7 @@ _Py_dg_strtod(const char *s00, char **se) | |||
| 1349 | 1349 | BCinfo bc; | |
| 1350 | 1350 | Bigint *bb, *bb1, *bd, *bd0, *bs, *delta; | |
| 1351 | 1351 | ||
| 1352 | - sign = nz0 = nz = dplen = 0; | ||
| 1352 | + sign = nz0 = nz = 0; | ||
| 1353 | 1353 | dval(&rv) = 0.; | |
| 1354 | 1354 | for(s = s00;;s++) switch(*s) { | |
| 1355 | 1355 | case '-': | |
@@ -1388,11 +1388,8 @@ _Py_dg_strtod(const char *s00, char **se) | |||
| 1388 | 1388 | else if (nd < 16) | |
| 1389 | 1389 | z = 10*z + c - '0'; | |
| 1390 | 1390 | nd0 = nd; | |
| 1391 | - dp0 = dp1 = s - s0; | ||
| 1392 | 1391 | if (c == '.') { | |
| 1393 | 1392 | c = *++s; | |
| 1394 | - dp1 = s - s0; | ||
| 1395 | - dplen = 1; | ||
| 1396 | 1393 | if (!nd) { | |
| 1397 | 1394 | for(; c == '0'; c = *++s) | |
| 1398 | 1395 | nz++; | |
@@ -1477,6 +1474,32 @@ _Py_dg_strtod(const char *s00, char **se) | |||
| 1477 | 1474 | ||
| 1478 | 1475 | if (!nd0) | |
| 1479 | 1476 | nd0 = nd; | |
| 1477 | + | ||
| 1478 | + /* Summary of parsing results. The parsing stage gives values | ||
| 1479 | + * s0, nd0, nd, e, y and z such that: | ||
| 1480 | + * | ||
| 1481 | + * - nd >= nd0 >= 1 | ||
| 1482 | + * | ||
| 1483 | + * - the nd significant digits are in s0[0:nd0] and s0[nd0+1:nd+1] | ||
| 1484 | + * (using the usual Python half-open slice notation) | ||
| 1485 | + * | ||
| 1486 | + * - the absolute value of the number represented by the original input | ||
| 1487 | + * string is n * 10**e, where n is the integer represented by the | ||
| 1488 | + * concatenation of s0[0:nd0] and s0[nd0+1:nd+1] | ||
| 1489 | + * | ||
| 1490 | + * - the first significant digit is nonzero | ||
| 1491 | + * | ||
| 1492 | + * - the last significant digit may or may not be nonzero; (some code | ||
| 1493 | + * currently assumes that it's nonzero; this is a bug) | ||
| 1494 | + * | ||
| 1495 | + * - y contains the value represented by the first min(9, nd) | ||
| 1496 | + * significant digits | ||
| 1497 | + * | ||
| 1498 | + * - if nd > 9, z contains the value represented by significant digits | ||
| 1499 | + * with indices in [9, min(16, nd)). So y * 10**(min(16, nd) - 9) + z | ||
| 1500 | + * gives the value represented by the first min(16, nd) sig. digits. | ||
| 1501 | + */ | ||
| 1502 | + | ||
| 1480 | 1503 | k = nd < DBL_DIG + 1 ? nd : DBL_DIG + 1; | |
| 1481 | 1504 | dval(&rv) = y; | |
| 1482 | 1505 | if (k > 9) { | |
@@ -1593,15 +1616,18 @@ _Py_dg_strtod(const char *s00, char **se) | |||
| 1593 | 1616 | /* ASSERT(STRTOD_DIGLIM >= 18); 18 == one more than the */ | |
| 1594 | 1617 | /* minimum number of decimal digits to distinguish double values */ | |
| 1595 | 1618 | /* in IEEE arithmetic. */ | |
| 1596 | - i = j = 18; | ||
| 1597 | - if (i > nd0) | ||
| 1598 | - j += dplen; | ||
| 1599 | - for(;;) { | ||
| 1600 | - if (--j <= dp1 && j >= dp0) | ||
| 1601 | - j = dp0 - 1; | ||
| 1602 | - if (s0[j] != '0') | ||
| 1603 | - break; | ||
| 1619 | + | ||
| 1620 | + /* Truncate input to 18 significant digits, then discard any trailing | ||
| 1621 | + zeros on the result by updating nd, nd0, e and y suitably. (There's | ||
| 1622 | + no need to update z; it's not reused beyond this point.) */ | ||
| 1623 | + for (i = 18; i > 0; ) { | ||
| 1624 | + /* scan back until we hit a nonzero digit. significant digit 'i' | ||
| 1625 | + is s0[i] if i < nd0, s0[i+1] if i >= nd0. */ | ||
| 1604 | 1626 | --i; | |
| 1627 | + if (s0[i < nd0 ? i : i+1] != '0') { | ||
| 1628 | + ++i; | ||
| 1629 | + break; | ||
| 1630 | + } | ||
| 1605 | 1631 | } | |
| 1606 | 1632 | e += nd - i; | |
| 1607 | 1633 | nd = i; | |
@@ -1611,8 +1637,8 @@ _Py_dg_strtod(const char *s00, char **se) | |||
| 1611 | 1637 | y = 0; | |
| 1612 | 1638 | for(i = 0; i < nd0; ++i) | |
| 1613 | 1639 | y = 10*y + s0[i] - '0'; | |
| 1614 | - for(j = dp1; i < nd; ++i) | ||
| 1615 | - y = 10*y + s0[j++] - '0'; | ||
| 1640 | + for(; i < nd; ++i) | ||
| 1641 | + y = 10*y + s0[i+1] - '0'; | ||
| 1616 | 1642 | } | |
| 1617 | 1643 | } | |
| 1618 | 1644 | bd0 = s2b(s0, nd0, nd, y); | |
| Back | FazBrowse Home | New Git URL |
0 commit comments