首页 > 解决方案 > 如何修复 TypeError:“添加”对象不可调用?

问题描述

def f(x):
    f='exp(x)-x-2'
    y=eval(f)
    print(y)
    return y
def bissection(f,f_line,f_2lines,a,b,epsilon1,epsilon2):
    x=a
    result_a=f(a)
    x=b
    result_b=f(b)
    if (f.evalf(a)*f.evalf(b)>=0):
        print("Interval [a,b] does not contain a zero ")
        exit()
    zeta=min(epsilon1,epsilon2)/10
    x=a
    while(f_line(x)>0):
        if(x<b or x>-b):
            x=x+zeta
        else:
            stop  
    ak=a
    bk=b
    xk=(ak+bk)/2
    k=0
    if (f(xk)*f(ak)<0):
        ak=ak
        bk=xk
    if (f(xk)*f(bk)<0):
        ak=xk
        bk=bk
    k=k+1
from sympy import *
import math
x=Symbol('x')
f=exp(x)-x-2
f_line=f.diff(x)                   
f_2lines=f_line.diff(x)           
print("Derivative of f:", f_line)    
print("2nd Derivative of f:", f_2lines) 
a=int(input('Beginning of interval: '))
b=int(input('End of interval: '))
epsilon1=input('1st tolerance: ')
epsilon2=input('2nd tolerance: ')
bissection(f,f_line,f_2lines,a,b,epsilon1,epsilon2)

该程序是实施二分法的尝试。我试过写两个函数:

第一个 f 应该接收可能包含或不包含根(a 和 b)的区间的极值,并返回在这一点上评估的函数的值。

第二个,二等分,应该接收函数、函数的一阶和二阶导数、区间的极值 (a,b) 和两个容差 (epsilon1,epsilon2)。

我想要做的是将每个值a和b,一次一个,作为函数f的参数,它应该返回f(a)和f(b);也就是说,函数在每个点 a 和 b 中的值。

然后,它应该测试两个条件:1)如果在区间的极端函数值具有相反的符号。如果他们不这样做,该方法将不会在此时间间隔内收敛,那么程序应该终止。

if(f.evalf(a)*f.evalf(b)>=0)
    exit()

2)

while(f_line(x)>0): #while the first derivative of the function evaluated in x is positive
    if(x<b or x>-b):     #This should test whether x belongs to the interval [a,b]
        x=x+zeta                                #If it does, x should receive x plus zeta
    else:
        stop

在这个循环结束时,我的目标是确定一阶导数是否严格为正(我还没有做负例)。

问题:我收到了错误

Traceback (most recent call last):
   File "bissec.py", line 96, in <module>
       bissection(f,f_line,f_2lines,a,b,epsilon1,epsilon2)
   File "bissec.py", line 41, in bissection
       result_a=f(a)
TypeError: 'Add' object is not callable

如何正确调用该函数,以便它为每个需要的 x 返回函数的值(在本例中为 f(x)=exp(x)-x-2)?也就是说,我如何评估 f(a) 和 f(b)?

标签: pythonfunctiontypeerrorsympy

解决方案


好的,所以我已经弄清楚您的程序在哪里失败了,我有 4 个原因。

首先,你的问题的主要主题是,如果你想评估一个函数f以获得一个确定x的值,比如说a,你需要使用f.subs(x, a).evalf(),正如SymPy 文档中描述的那样。您以两种不同的方式使用:f.evalf(2)f_line(a); 两者都是错误的,需要用正确的语法代替。

其次,如果您想停止 while 循环,您应该使用break代码中所写的关键字,而不是“停止”。

第三,避免对变量和函数使用相同的名称。在您的f函数中,您还用作f变量的名称。在bissection函数中,您f作为参数传递并尝试调用该f函数。那也会失败。相反,我已将f函数更改为f_calc,并在其中应用了我第一点的正确语法。

第四,您的epsilon1epsilon2输入缺少float()转换。我已经添加了。

现在,我还编辑了您的代码以使用良好实践并应用PEP8

此代码应修复您遇到的此错误以及其他一些错误:

from sympy import *


def func_calc(func, x, val):
    """Evaluate a given function func, whose varible is x, with value val"""
    return func.subs(x, val).evalf()


def bissection(x, f, f_line, f_2lines, a, b, epsilon1, epsilon2):
    """Applies the Bissection Method"""

    result_a = func_calc(f, x, a)
    result_b = func_calc(f, x, b)

    if (result_a * result_b >= 0):
        print("Interval [a,b] does not contain a zero")
        exit()

    zeta = min(epsilon1, epsilon2) / 10
    x_val = a
    while(func_calc(f_line, x, a) > 0):
        if(-b < x_val or x_val < b):
            x_val = x_val + zeta
        else:
            break  # the keyword you're looking for is break, instead of "stop"

    print(x_val)
    ak = a
    bk = b
    xk = (ak + bk) / 2
    k = 0
    if (func_calc(f, x, xk) * func_calc(f, x, ak) < 0):
        ak = ak
        bk = xk
    if (func_calc(f, x, xk) * func_calc(f, x, bk) < 0):
        ak = xk
        bk = bk
    k = k + 1


def main():
    x = Symbol('x')
    f = exp(x) - x - 2
    f_line = f.diff(x)
    f_2lines = f_line.diff(x)
    print("Derivative of f:", f_line)
    print("2nd Derivative of f:", f_2lines)
    a = int(input('Beginning of interval: '))
    b = int(input('End of interval: '))
    epsilon1 = float(input('1st tolerance: '))
    epsilon2 = float(input('2nd tolerance: '))
    bissection(x, f, f_line, f_2lines, a, b, epsilon1, epsilon2)


if __name__ == '__main__':
    main()

推荐阅读