[Python-checkins] bpo-44954: Fix wrong result in float.fromhex corner case (GH-27834)
mdickinson
webhook-mailer at python.org
Fri Aug 20 06:40:21 EDT 2021
https://github.com/python/cpython/commit/60b93d9e4922eeae25052bc15909d1f4152babde
commit: 60b93d9e4922eeae25052bc15909d1f4152babde
branch: main
author: Mark Dickinson <mdickinson at enthought.com>
committer: mdickinson <dickinsm at gmail.com>
date: 2021-08-20T11:40:11+01:00
summary:
bpo-44954: Fix wrong result in float.fromhex corner case (GH-27834)
files:
A Misc/NEWS.d/next/Core and Builtins/2021-08-19-14-43-24.bpo-44954.dLn3lg.rst
M Lib/test/test_float.py
M Objects/floatobject.c
diff --git a/Lib/test/test_float.py b/Lib/test/test_float.py
index 38a17cedd6446f..29f775644dd4a8 100644
--- a/Lib/test/test_float.py
+++ b/Lib/test/test_float.py
@@ -1468,6 +1468,20 @@ def test_from_hex(self):
self.identical(fromHex('0X1.0000000000001fp0'), 1.0+2*EPS)
self.identical(fromHex('0x1.00000000000020p0'), 1.0+2*EPS)
+ # Regression test for a corner-case bug reported in b.p.o. 44954
+ self.identical(fromHex('0x.8p-1074'), 0.0)
+ self.identical(fromHex('0x.80p-1074'), 0.0)
+ self.identical(fromHex('0x.81p-1074'), TINY)
+ self.identical(fromHex('0x8p-1078'), 0.0)
+ self.identical(fromHex('0x8.0p-1078'), 0.0)
+ self.identical(fromHex('0x8.1p-1078'), TINY)
+ self.identical(fromHex('0x80p-1082'), 0.0)
+ self.identical(fromHex('0x81p-1082'), TINY)
+ self.identical(fromHex('.8p-1074'), 0.0)
+ self.identical(fromHex('8p-1078'), 0.0)
+ self.identical(fromHex('-.8p-1074'), -0.0)
+ self.identical(fromHex('+8p-1078'), 0.0)
+
def test_roundtrip(self):
def roundtrip(x):
return fromHex(toHex(x))
diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-08-19-14-43-24.bpo-44954.dLn3lg.rst b/Misc/NEWS.d/next/Core and Builtins/2021-08-19-14-43-24.bpo-44954.dLn3lg.rst
new file mode 100644
index 00000000000000..4cdeb34b8b6116
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2021-08-19-14-43-24.bpo-44954.dLn3lg.rst
@@ -0,0 +1,2 @@
+Fixed a corner case bug where the result of ``float.fromhex('0x.8p-1074')``
+was rounded the wrong way.
diff --git a/Objects/floatobject.c b/Objects/floatobject.c
index 7e78132c01ca27..92faa7c1320237 100644
--- a/Objects/floatobject.c
+++ b/Objects/floatobject.c
@@ -1463,8 +1463,8 @@ float_fromhex(PyTypeObject *type, PyObject *string)
bits lsb, lsb-2, lsb-3, lsb-4, ... is 1. */
if ((digit & half_eps) != 0) {
round_up = 0;
- if ((digit & (3*half_eps-1)) != 0 ||
- (half_eps == 8 && (HEX_DIGIT(key_digit+1) & 1) != 0))
+ if ((digit & (3*half_eps-1)) != 0 || (half_eps == 8 &&
+ key_digit+1 < ndigits && (HEX_DIGIT(key_digit+1) & 1) != 0))
round_up = 1;
else
for (i = key_digit-1; i >= 0; i--)
More information about the Python-checkins
mailing list