2017-05-26 74 views
0

我正在为数学计算器编写代码,并且遇到问题。当我要求用户输入一个函数来派生时,他们输入一个数字,然后输入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) 

回答

2

的几个问题:

  1. 使用func以字符串形式的名称具有误导性(Python允许一阶的功能,因此你会期望它实际上是的一个函数);我们将其称为fn_str

  2. 如果clean_func正常工作,它将返回一个sympy可分析字符串 - 然后您将其传递到diff而不从字符串转换为函数。

  3. 建设

    for i in range(len(mystring)): 
        do_something(mystring[i]) 
    

    更清楚地写为

    for ch in mystring: 
        do_something(ch) 
    
  4. isinstance(func[i], int)不起作用,因为func[i]是一个字符的字符串,而不是一个整数。改为尝试str.isdecimal()

  5. self.math_symbols未定义。

  6. Python字符串是不可变的;每次你做mystring += ch它实际上创建一个全新的字符串。正因为如此,追加到字符串块列表然后"".join()完成时效率更高。

  7. for c in range(48, 57):Python范围不包括end的值,即这将产生48,49,50,... 56.这意味着chr(57),即“9”永远不会被测试。

  8. 同样,字符串切片不包括end偏移量,所以func[i:i+1]是一个字符,完全等效于func[i]。你的意思是func[i:i+2]

  9. 此外,像3.是一个有效的Python浮点数,但您的代码不会赶上3.x。做适当的标记而不是逐个字符的比较可以理解这一点。

  10. 该类不是衍生物;你正试图将你的程序加入错误标记的类中。

清洁的后续版本:

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 
+0

所以我把你干净的FUNC键,把它放在我的数学课,因为这是一类具有一许多子类,所以我会清理大量的fn_str,然后只是衍生物。然而,我不认为我能够访问它,因为它在我的派生类 –

+0

的外侧我试图只做Math.clean(fn_str),但是我得到它缺少“fn_str”的补充,所以我很困惑 –

+0

只要(a)它仍然是类方法,(b)它可以访问NUMCHARS,VARCHARS,OPCHARS,LEGALCHARS,它应该可以很好地作为Math类的一部分。你能分享你目前的实际代码吗? hugh_bothwell at hotmail dot com –

相关问题