2017-05-26 60 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 –

相關問題