]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
bpo-44954: Fix wrong result in float.fromhex corner case (GH-27834) (GH-27855)
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>
Fri, 20 Aug 2021 11:37:41 +0000 (04:37 -0700)
committerGitHub <noreply@github.com>
Fri, 20 Aug 2021 11:37:41 +0000 (12:37 +0100)
(cherry picked from commit 60b93d9e4922eeae25052bc15909d1f4152babde)

Co-authored-by: Mark Dickinson <mdickinson@enthought.com>
Lib/test/test_float.py
Misc/NEWS.d/next/Core and Builtins/2021-08-19-14-43-24.bpo-44954.dLn3lg.rst [new file with mode: 0644]
Objects/floatobject.c

index 4f66b41e0ad0ecad615eb9d0a653b68a4478b93a..fcb87491c2a434b7c49d55a5ece514b0ae4af666 100644 (file)
@@ -1446,6 +1446,20 @@ class HexFloatTestCase(unittest.TestCase):
         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 (file)
index 0000000..4cdeb34
--- /dev/null
@@ -0,0 +1,2 @@
+Fixed a corner case bug where the result of ``float.fromhex('0x.8p-1074')``
+was rounded the wrong way.
index 9f5014092cf20a6124572c006a8775b6fb137c96..6adc90ab9a2c34f758ba37b272ad1500056cb5ee 100644 (file)
@@ -1443,8 +1443,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--)