This issue tracker has been migrated to GitHub,
and is currently read-only.
For more information,
see the GitHub FAQs in the Python's Developer Guide.
This issue tracker has been migrated to GitHub,
and is currently read-only.
For more information,
see the GitHub FAQs in the Python's Developer Guide.
Created on 2022-03-26 22:10 by steven.daprano, last changed 2022-04-11 14:59 by admin.
Messages (2) | |||
---|---|---|---|
msg416093 - (view) | Author: Steven D'Aprano (steven.daprano) * | Date: 2022-03-26 22:10 | |
OverflowError sometimes (but not always) includes some sort of numeric code: >>> 1e+300 ** 2 Traceback (most recent call last): File "<stdin>", line 1, in <module> OverflowError: (34, 'Numerical result out of range') but the meaning of the 34 is not documented: https://docs.python.org/3/library/exceptions.html#OverflowError help(OverflowError) is no more insightful, saying only: __init__(self, /, *args, **kwargs) Initialize self. See help(type(self)) for accurate signature. Other OverflowError exceptions do not include the numeric code: >>> math.exp(10000) Traceback (most recent call last): File "<stdin>", line 1, in <module> OverflowError: math range error Is it an error code from C? Something to do with the number of digits of precision? An easter-egg to do with The Count Of Monte Cristo? |
|||
msg416096 - (view) | Author: Eryk Sun (eryksun) * | Date: 2022-03-26 22:46 | |
The error code for `1e+300 ** 2` is ERANGE, from calling libm pow(). Since pow() returns a double, there's no way to indicate an error in the return value. Instead, C errno is set to 0 beforehand and checked for a non-zero error value after the call. If the error code isn't ERANGE, then float.__pow__() raises ValueError instead of OverflowError. Here's the relevant snippet from float_pow() in Objects/floatobject.c: /* Now iv and iw are finite, iw is nonzero, and iv is * positive and not equal to 1.0. We finally allow * the platform pow to step in and do the rest. */ errno = 0; ix = pow(iv, iw); _Py_ADJUST_ERANGE1(ix); if (negate_result) ix = -ix; if (errno != 0) { /* We don't expect any errno value other than ERANGE, but * the range of libm bugs appears unbounded. */ PyErr_SetFromErrno(errno == ERANGE ? PyExc_OverflowError : PyExc_ValueError); return NULL; } return PyFloat_FromDouble(ix); Here's a direct example using ctypes: import ctypes import errno libm = ctypes.CDLL('libm.so.6', use_errno=True) libm.pow.argtypes = (ctypes.c_double, ctypes.c_double) libm.pow.restype = ctypes.c_double >>> errno.ERANGE 34 >>> ctypes.set_errno(0) 0 >>> libm.pow(1e300, 2) inf >>> ctypes.get_errno() == errno.ERANGE True |
History | |||
---|---|---|---|
Date | User | Action | Args |
2022-04-11 14:59:57 | admin | set | github: 91290 |
2022-03-26 22:46:01 | eryksun | set | nosy:
+ eryksun messages: + msg416096 |
2022-03-26 22:10:10 | steven.daprano | create |