为什么来自sympy的lambdify函数会在我的情况下抛出错误?

时间:2018-02-09 20:00:34

标签: python-3.x math sympy newtons-method lambdify

错误在于lambdify函数。它出于某种原因说语法错误。 这正是所说的:

  

文件" D:\ Anaconda \ lib \ site-packages \ sympy \ utilities \ lambdify.py",第434行,lambdify func = eval(lstr,namespace)。

程序在用户输入容差后立即崩溃。这是一个牛顿方法程序(或者至少是我的尝试)。任何有关如何改进此代码的建议也将非常受欢迎。

我为fdfdx输入的内容如下:

x**3 + 3*x + 5 

3*x**2 + 3 

分别。至于v0eps,我分别输入10.000001。无论我输入什么,程序都会以上述错误终止(假设它使用x作为变量,否则它表示未定义且表示它)。

import sympy
import sys

v0 = int(input("Please enter the v0 value: "))

eps = float(input("Please enter the tolerance: "))

f = lambda x : eval('input("Enter the function: ")')

dfdx = lambda x : eval('input("Enter the derivative: ")')

x=sympy.symbols('x')

func = sympy.lambdify(f,x)

deriv = sympy.lambdify(f,x)

def Newton(func, deriv, v0, eps):
    f_value = func(v0)
    iteration_counter = 0
    while abs(f_value) > eps and iteration_counter < 100:
        try:
            v0 = v0 - float(f_value)/deriv(v0)
        except ZeroDivisionError:
            print ("Error! - derivative zero for x = ", v0)
            sys.exit(1)     # Abort with error

        f_value = func(v0)
        iteration_counter += 1

    # Here, either a solution is found, or too many iterations
    if abs(f_value) > eps:
        iteration_counter = -1
    return v0, iteration_counter

Newton(func,deriv,v0,eps)

1 个答案:

答案 0 :(得分:1)

AFAIU你的狡猾计划是首先使用Python解释器从用户的字符串(使用input)构建一个函数,然后使用SymPy从中构建一个可重用的函数。您的代码存在一些问题,最重要的可能是您对SymPy方法的签名错误。

提供dfdx作为输入的想法对我来说并不好看。如果原始函数f具有可以计算的良好导数,SymPy可以自己计算它。

因此,如果你修复了一些明显的错误,你可能会得到这样的代码:

Python 3.x

import sympy
import sys

v0 = int(input("Please enter the v0 value: "))
eps = float(input("Please enter the tolerance: "))
f_inp = lambda x: eval(input("Enter the function: "))
x = sympy.symbols('x')
f_symb = f_inp(x)
func = sympy.lambdify(x, f_symb)
deriv = sympy.lambdify(x, sympy.diff(f_symb, x))

def Newton(func, deriv, v0, eps):
    f_value = func(v0)
    iteration_counter = 0
    while abs(f_value) > eps and iteration_counter < 100:
        try:
            v0 = v0 - float(f_value) / deriv(v0)
        except ZeroDivisionError:
            print ("Error! - derivative zero for x = ", v0)
            sys.exit(1)  # Abort with error

        f_value = func(v0)
        iteration_counter += 1

    # Here, either a solution is found, or too many iterations
    if abs(f_value) > eps:
        iteration_counter = -1
    return v0, iteration_counter

print (Newton(func, deriv, v0, eps))

Python 2.x

import sympy
import sys

v0 = int(input("Please enter the v0 value: "))
eps = float(input("Please enter the tolerance: "))
f_inp = lambda x: input("Enter the function: ")
x = sympy.symbols('x')
f_symb = f_inp(x)
func = sympy.lambdify(x, f_symb)
deriv = sympy.lambdify(x, sympy.diff(f_symb, x))

def Newton(func, deriv, v0, eps):
    f_value = func(v0)
    iteration_counter = 0
    while abs(f_value) > eps and iteration_counter < 100:
        try:
            v0 = v0 - float(f_value) / deriv(v0)
        except ZeroDivisionError:
            print ("Error! - derivative zero for x = ", v0)
            sys.exit(1)  # Abort with error

        f_value = func(v0)
        iteration_counter += 1

    # Here, either a solution is found, or too many iterations
    if abs(f_value) > eps:
        iteration_counter = -1
    return v0, iteration_counter

print Newton(func, deriv, v0, eps)

您的输入

1
0.000001
x**3 + 3*x + 5 

产生以下输出:

  

( - 1.154171557329764,5)

2.x和3.x版本之间的主要区别在于input in 2.x调用内部eval,而input in 3.x不调用。{/ p>