为什么math.log会导致ValueError: math domain error错误?

136

我只是在测试来自使用Python的工程数值方法一书中的示例。

from numpy import zeros, array
from math import sin, log
from newtonRaphson2 import *

def f(x):
    f = zeros(len(x))
    f[0] = sin(x[0]) + x[1]**2 + log(x[2]) - 7.0
    f[1] = 3.0*x[0] + 2.0**x[1] - x[2]**3 + 1.0
    f[2] = x[0] + x[1] + x[2] -5.0
    return f
    
x = array([1.0, 1.0, 1.0])
print(newtonRaphson2(f,x))

当我运行它时,它显示以下错误:

File "example NR2method.py", line 8, in f
    f[0] = sin(x[0]) + x[1]**2 + log(x[2]) - 7.0
ValueError: math domain error

我已经缩小了问题范围,确定是由于日志函数导致的,因为当我删除日志并添加一个不同的函数时,它可以工作。我认为这是由于与基础部分的某种干扰,但我无法弄清楚原因。请问有人能提供解决方案吗?


另请参见:使用math.acos函数出现Python math domain error的等效问题;使用math.sqrt函数出现Python math domain error的等效问题。

5个回答

172

您的代码对小于等于零的数进行了log运算。这在数学上是未定义的,因此Python的log函数会引发异常。以下是一个示例:

>>> from math import log
>>> log(-1)
Traceback (most recent call last):
  File "<pyshell#59>", line 1, in <module>
    log(-1)
ValueError: math domain error

如果不知道您的newtonRaphson2函数是做什么的,我无法猜测无效的x[2]值来自何处,但希望这能指引您找对方向。


我不明白为什么要进行负对数运算,因为这个定义是在定义方程组,也就是 x[0]、x[1] 和 x[2] 是变量 x、y 和 z,而牛顿-拉夫逊方法需要这些方程来求解。 - ramanunni.pm
1
另外,正如我在上面的代码中所定义的那样,当我说x[2] = 1.0时,log(1) = 0,至少我是这么认为的,也许我错了..不过还是谢谢你的帮助。 - ramanunni.pm
2
在你的函数f开头添加一个print x语句。这样你就可以看到方程求解器如何逐步尝试不同的x值,从而导致错误。 - mtadd
3
在我的情况下,问题不是参数为负数,而是恰好等于0,这会导致相同的异常(对于具有JS背景的人来说可能会感到惊讶,在那里Math.log(0)只是-Infinity)。 - qbolec

4
你也可以使用math.log1p函数。
根据官方文档

math.log1p(x)

返回1+x的自然对数(以e为底)。该结果是在x接近零时精确计算的。

你可以使用math.expm1将值转换回原始值,其返回e的x次幂减1。

4
你可能会因以下原因之一而出现数学域错误: 要么你试图在对数函数内使用负数,要么是零值。

3
当我们使用math库中的log()sqrt()时,会遇到这个问题。在这个"数学域错误"问题中,我们使用了一个负数(如-1)或0,在这些情况下是不应该使用的。

2
您正在尝试对非正数进行对数运算。
对数是在给出一个数字和它被提高的幂之后计算出底数的。log(0)表示某个数被提高到2次幂结果为0。指数永远不可能等于0*,这意味着log(0)没有答案,因此会抛出math domain error。
*注意:0^0可以得到0,但同时也可以得到1。这个问题存在激烈争议。
注:原始答案翻译成“最初的回答”

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