Python不确定性包中的零除错误

4
为什么会出现以下的零除错误?
>>> 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

这两个是否应该返回0.0

3
我觉得你说得对。这种情况也发生在 2.6 版本中。或许你应该直接向 uncertainties 的作者 Eric Lebigot (EOL) 报告问题。他会欢迎你的反馈。 - joaquin
这个问题在不确定性包的2.3.5版本中得到了正确处理! - Eric O. Lebigot
2个回答

3

情况非常微妙:

  1. On one hand, you're right, both results should mathematically be 0.

    In fact, the behavior should be the same as Python's:

    >>> 0.**0.3
    0.0
    

    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±0 is special: a**x is 0 for positive x, even if x has an uncertainty (the result is undefined for zero or negative x values). On the other hand, if a=0±0.1, the value of a**x is undefined because one cannot take the (real) power of a negative number (and a can be negative, if it has a non-zero uncertainty) (unless one uses complex numbers, which is not the purpose of the uncertainties package).

  2. 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 of a**x might later be undefined; reciprocally, if a = 0±0.3, the result should be undefined, but should somehow become 0 if the uncertainty of a is later changed to 0.

技术上讲,这归结于当0a**x在a=0处被定义但不可导:零不确定性的情况应该可行(函数被定义了),但非零不确定性必须产生错误(导数未定义)。这两种情况都必须以某种动态方式处理,因为用户可以随时更改不确定度。
这是一个有趣的情况,所以我会再次思考是否可以以某种优雅的方式修改不确定性模块并容纳这个问题。
PS:从版本2.3.5开始,不确定性包正确处理问题的情况,更一般地说,即使具有零不确定性的数字(即使同一数字但具有非零不确定性通过误差的线性传播而导致未定义错误,例如在问题中)

0

我认为只要指数小于1,就会发生ZeroDivisionError。代码的这部分正在尝试求导数。我模糊记得高中微积分告诉我,x ** y的导数是y * x ** (y - 1)

话虽如此,我同意你的例子应该计算结果为0。也许我们的直觉是错的(尽管我的微积分很差,我对真正的数学家和科学家对不确定性的处理方式一无所知,而且编写这个程序包的人似乎知道他在做什么,而且包含了很多测试),或者我们确实是对的,他需要增加处理把零(零的不确定性)的特殊情况提升为幂次的功能。


1
你对导数的形式是正确的,但当y小于1时并没有问题。当x为负数时会遇到问题,但我认为对于x >= 0不应该是一个问题。 - user545424
不,当求导之前的指数小于1时,这是一个问题。因为求导后会有负指数,而负指数等同于除法,所以导数将会出现除以零的情况。 - John Y
啊,我明白了。他确实需要评估 df(a=0)/da 的导数,这种情况下就会出现这个问题。 - user545424
而对于 df/dx,这将涉及到 log(0)。哎呀!现在一切都有意义了。 - user545424

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接