Skip to content

Commit 7ef0673

Browse files
bpo-44954: Fix wrong result in float.fromhex corner case (GH-27834) (GH-27855)
(cherry picked from commit 60b93d9) Co-authored-by: Mark Dickinson <mdickinson@enthought.com>
1 parent 0215257 commit 7ef0673

File tree

3 files changed

+18
-2
lines changed

3 files changed

+18
-2
lines changed

Lib/test/test_float.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1446,6 +1446,20 @@ def test_from_hex(self):
14461446
self.identical(fromHex('0X1.0000000000001fp0'), 1.0+2*EPS)
14471447
self.identical(fromHex('0x1.00000000000020p0'), 1.0+2*EPS)
14481448

1449+
# Regression test for a corner-case bug reported in b.p.o. 44954
1450+
self.identical(fromHex('0x.8p-1074'), 0.0)
1451+
self.identical(fromHex('0x.80p-1074'), 0.0)
1452+
self.identical(fromHex('0x.81p-1074'), TINY)
1453+
self.identical(fromHex('0x8p-1078'), 0.0)
1454+
self.identical(fromHex('0x8.0p-1078'), 0.0)
1455+
self.identical(fromHex('0x8.1p-1078'), TINY)
1456+
self.identical(fromHex('0x80p-1082'), 0.0)
1457+
self.identical(fromHex('0x81p-1082'), TINY)
1458+
self.identical(fromHex('.8p-1074'), 0.0)
1459+
self.identical(fromHex('8p-1078'), 0.0)
1460+
self.identical(fromHex('-.8p-1074'), -0.0)
1461+
self.identical(fromHex('+8p-1078'), 0.0)
1462+
14491463
def test_roundtrip(self):
14501464
def roundtrip(x):
14511465
return fromHex(toHex(x))
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fixed a corner case bug where the result of ``float.fromhex('0x.8p-1074')``
2+
was rounded the wrong way.

Objects/floatobject.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1443,8 +1443,8 @@ float_fromhex(PyTypeObject *type, PyObject *string)
14431443
bits lsb, lsb-2, lsb-3, lsb-4, ... is 1. */
14441444
if ((digit & half_eps) != 0) {
14451445
round_up = 0;
1446-
if ((digit & (3*half_eps-1)) != 0 ||
1447-
(half_eps == 8 && (HEX_DIGIT(key_digit+1) & 1) != 0))
1446+
if ((digit & (3*half_eps-1)) != 0 || (half_eps == 8 &&
1447+
key_digit+1 < ndigits && (HEX_DIGIT(key_digit+1) & 1) != 0))
14481448
round_up = 1;
14491449
else
14501450
for (i = key_digit-1; i >= 0; i--)

0 commit comments

Comments
 (0)