I’m trying to figure out the pattern here:
>>> 1e300 ** 2
OverflowError: (34, 'Result too large')
>>> 1e300j ** 2
OverflowError: complex exponentiation
>>> (1e300 + 1j) ** 2
OverflowError: complex exponentiation
>>> (1e300 + 1e300j) ** 2
(nan+nanj)
The behavior seems to be not only unspecified in theory, but also weird in practice! What explains this?
A look at the source for complex exponentiation shows that Python only checks for overflow at the end of the computation. Also, there's a special case for small integer exponents that uses exponentiation by squaring, which involves complex multiplication.
r.real = a.real*b.real - a.imag*b.imag;
r.imag = a.real*b.imag + a.imag*b.real;
This is the formula for complex multiplication. Note the following:
a.real*b.real - a.imag*b.imag
When a
and b
are very large, this becomes floating-point infinity minus floating-point infinity, which is nan
. The nan
results propagate, and after a few operations, the result is (nan+nanj)
. Py_ADJUST_ERANGE2
only sets errno
if it sees an infinity, so it misses the overflow and goes on its way.
In summary, Python only checks the end result for overflow, not intermediate values, and this causes it to miss the overflow in the middle because it's all nan
s by the end. The expressions that do raise OverflowError
do so because they never try to subtract infinities, so the error is spotted by the end. It doesn't look like a deliberate design decision; you could fix it by changing the way the overflow check works.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With