Why does the following zero division error occur?
>>> from uncertainties import ufloat
>>> a = ufloat((0,0))
>>> x = ufloat((0.3,0.017))
>>> a**x
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/uncertainties/__init__.py", line 601, in f_with_affine_output
if arg.derivatives
File "<string>", line 1, in <lambda>
ZeroDivisionError: 0.0 cannot be raised to a negative power
>>> 0.0**x
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/uncertainties/__init__.py", line 601, in f_with_affine_output
if arg.derivatives
File "<string>", line 1, in <lambda>
ValueError: math domain error
Shouldn’t these both just return 0.0?
The situation is quite subtle:
On one hand, you’re right, both results should mathematically be 0.
In fact, the behavior should be the same as Python’s:
When the exponent has an uncertainty the result should thus be
exactly 0 (no uncertainty), since the Python result is always 0.
The case
a = 0±0is special:a**xis 0 for positivex, even ifxhas an uncertainty (the result is undefined for zero or negativexvalues). On the other hand, ifa=0±0.1, the value ofa**xis undefined because one cannot take the (real) power of a negative
number (and
acan be negative, if it has a non-zero uncertainty) (unless one usescomplex numbers, which is not the purpose of the uncertainties
package).
On the other hand, the uncertainties module allows users to change the uncertainties of numbers at any time and still get correct results. This clashes with the “ideal” mathematical results above: if
a = 0±0, then the result ofa**xmight later be undefined; reciprocally, ifa = 0±0.3, the result should be undefined, but should somehow become 0 if the uncertainty ofais later changed to 0.Technically, this all boils down to the fact that
a**xwith 0 < x < 1 is defined in a = 0 but is not differentiable there: the case of a zero uncertainty should work (the function is defined), but a non-zero uncertainty must yield an error (the derivative is not defined). Both of these cases have to somehow be handled dynamically, since the uncertainties can be changed on-the-fly by the user.This is an interesting situation, so I will think again about whether the uncertainties module can be modified in some elegant way and accomodate this issue.
PS: Starting with version 2.3.5, the uncertainties package correctly handles the cases of the question, and more generally all cases where a number with uncertainty actually has a zero uncertainty (even if the same number but with a non-zero uncertainty would give an undefined error through linear propagation of error, like in the question).