是什么原因导致plot()的意外行为

时间:2012-05-04 04:04:15

标签: python sage

def f(u):
    value = 0.0
    if u > -1 and u < 1:
        value = u * u
    return value

鉴于上述情况,以下内容产生了预期的情节:

plot(f,(x,-5,5))

但是plot(f(x),(x,-5,5))只是绘制一条水平线。谁能解释一下发生了什么?

3 个答案:

答案 0 :(得分:1)

前者传递函数,允许在plot()内调用它。后者调用函数一次并传递返回的值,每次都得到相同的值。

答案 1 :(得分:1)

类似于@Ignacio所说的,原因是被调用的函数一次。与sin等其他函数相比,这个问题是有条件的。调用函数时会计算if语句,而不会将其保留为符号语句。也就是说,u > -1 and u < 1 [1] 在第一个函数调用上进行评估,并相应地处理result(即留在0)。

作为正在发生的事情的例证:

sage: x = var('x')
sage: print ":)" if x > 0 else ":("
:(

一般 [2] 没有办法解决这个问题,因为Python必须在if语句中评估条件,以确定函数时要采用的代码路径被称为。

最佳案例解决方案

有一个解决方案应该有效(但还没有)。 Sage提供Piecewise,因此您可以将f定义为:

f = Piecewise([((-5, -1), ConstantFunction(0)), 
               ((-1, 1),     x*x), 
               ((1, 5),   ConstantFunction(0))],
              x)

不幸的是,Piecewise的实现尚未完成,而且严重缺乏,因此绘制此图的唯一方法似乎是:

f.plot()

(限制:尝试使用变量调用f会导致错误;它无法与传统的plot一起使用;您无法在Piecewise.plot中限制域,它会绘制整个事情(因此我将其限制在±5);它不能应付无限的间隔。)

工作解决方案

您还可以检测f的参数是数字还是变量,并根据该参数执行相应的操作:

def f(u):
    try:
        float(u) # see it's a number by trying to convert
        return u*u if -1 < u < 1 else 0.0
    except TypeError: # the conversion failed
        if callable(f):
            return lambda uu: f(u(uu))
        else:
            return f

请注意callable调用,它会检查u是否为函数(在某种意义上),如果是,则返回fu的组合。< / p>

此版本允许我们执行以下操作:

sage: f(10)
0.0
sage: f(x)(0.5)
0.25
sage: f(x+3)(-2.2)
0.64

它也适用于任何形式的plot。 (虽然它因DeprecationWarnings语法而警告u(uu);但是有一些方法可以使用u.variables解决这个问题,但它们相当尴尬。)

注意:这种“工作”解决方案非常脆弱,非常不理想;如果有效,Piecewise版本将是正确的解决方案。

[1]:Python实际上允许您将其写为-1 < u < 1。很酷。

[2]:虽然在某些特殊情况下你可以,例如如果您知道x > 0,则可以使用assume(x > 0),这意味着该示例将打印:)

答案 2 :(得分:0)

现在,这是一个(可能)更简单的解决方案,使用lambdas。

sage: plot(lambda x:f(x), (x,-5,5))

plot of your function