我正在为数学计算器编写代码,并且遇到了问题。当我要求用户输入要派生的函数时,他们输入一个数字,然后输入x,如3x,而不是3 * x。代码崩溃,因为它无法解析它。为了解决这个问题,我有一个消毒功能,但由于某些原因,它甚至无法运行。
class Derivatives:
def __init__(self):
x=sympy.Symbol('x')
self.func=self.clean_func((input("Enter f(x): ")))
print(self.func)
print(sympy.diff(self.func, x))
def clean_func(self, func):
clean_func=""
print("c")
for i in range(len(func)):
if func[i].isalpha or isinstance(func[i], int) or func[i] in self.math_symbols :
if func[i]== "^" :
clean_func+="**"
else:
clean_func+=func[i]
for c in range(48, 57) :
if func[i:i+1] == (chr(c) + 'x') :
clean_func+="*" #helps with parsing
return clean_func
我在a=Derivatives()
Enter f(x): 3x
Traceback (most recent call last):
File "<ipython-input-48-f4cd19afbde9>", line 1, in <module>
a=Derivatives()
File "/Volumes/PROJECTS/M_series.py", line 71, in __init__
x=sympy.Symbol('x')
File "/Users/thomastierney/anaconda/lib/python3.5/site-packages/sympy/core/function.py", line 1691, in diff
return Derivative(f, *symbols, **kwargs)
File "/Users/thomastierney/anaconda/lib/python3.5/site-packages/sympy/core/function.py", line 1018, in __new__
expr = sympify(expr)
File "/Users/thomastierney/anaconda/lib/python3.5/site-packages/sympy/core/sympify.py", line 324, in sympify
raise SympifyError('could not parse %r' % a, exc)
SympifyError: Sympify of expression 'could not parse '3x'' failed, because of exception being raised:
SyntaxError: invalid syntax (<string>, line 1)
答案 0 :(得分:2)
一些问题:
使用func
作为字符串的名称具有误导性(Python允许使用一阶函数,因此您可能希望它实际上是一个函数);我们改为称之为fn_str
。
如果clean_func
正常工作,它将返回一个sympy
- 可解析的字符串 - 然后将其传递给diff
,而不从字符串转换为函数。
施工
for i in range(len(mystring)):
do_something(mystring[i])
更明确地写为
for ch in mystring:
do_something(ch)
isinstance(func[i], int)
无法正常工作,因为func[i]
是一个字符的字符串,而不是整数。请改为str.isdecimal()
。
self.math_symbols
未定义。
Python字符串是不可变的;每次执行mystring += ch
时,它实际上都会创建一个全新的字符串。因此,在完成后附加到字符串块列表然后"".join()
它们会更有效率。
for c in range(48, 57)
:Python范围不包含end
值,即这将产生48,49,50,... 56.这意味着chr(57)即&#34 ; 9&#34;从未进行过测试。
同样,字符串切片不包含end
偏移量,因此func[i:i+1]
是一个字符,完全等同于func[i]
。你的意思是func[i:i+2]
。
此外,3.
之类的内容是有效的Python浮点数,但您的代码不会捕获3.x
。进行适当的标记化而不是逐个字符的比较可以捕捉到它。
该课程不是衍生品;你试图将你的程序填入错误标记的课程中。
清理版本:
import string
import sympy
# This could easily be just a function;
# I made it a class to keep the namespace clean
class FnStrCleaner:
# valid characters
NUMCHARS = set(string.digits + ".")
VARCHARS = set(string.ascii_letters)
OPCHARS = set("()+-*/^")
LEGALCHARS = NUMCHARS | VARCHARS | OPCHARS
@classmethod
def clean(cls, fn_str):
# generator expression - skip nonlegal chars
good_chars = (ch for ch in fn_str if ch in cls.LEGALCHARS)
out = []
# simple FSM to process character stream
prev_num = False # preceding character was part of a number
for ch in good_chars:
if prev_num:
if ch in cls.NUMCHARS:
out.append(ch)
# prev_num = True
elif ch in cls.VARCHARS:
out.append('*' + ch)
prev_num = False
else: # ch in cls.OPCHARS
out.append(ch)
prev_num = False
else:
if ch in cls.NUMCHARS:
out.append(ch)
prev_num = True
elif ch in cls.VARCHARS:
out.append(ch)
# prev_num = False
else: # ch in cls.OPCHARS
out.append('**' if ch == '^' else ch)
# prev_num = False
return "".join(out)
def get_function(prompt, locals=None):
fn_str = input(prompt)
fn_str = FnStrCleaner.clean(fn_str)
return sympy.sympify(fn_str, locals=locals)
def main():
x = sympy.Symbol("x")
f = get_function("Enter f(x): ", {'x': x})
df = sympy.diff(f, x)
print("f(x) =", f)
print("f'(x) =", df)
if __name__ == "__main__":
main()
像
一样运行Enter f(x): 29x^3 + 12x^2 - 9x + 5
f(x) = 29*x**3 + 12*x**2 - 9*x + 5
f'(x) = 87*x**2 + 24*x - 9