2012-05-08 85 views
16

比方說,我有一個公式:如何在Python中求解方程?

2x + 6 = 12

代數一樣,我們可以看到,x = 3。我如何使用Python解決x的問題?我是編程新手,我看着eval()exec(),但我無法弄清楚如何讓他們做我想做的事。我不想使用外部庫(例如SAGE),我想用普通的Python來做到這一點。

+7

我想要一輛能在4.5秒內完成0到60的汽車並獲得45 MPG。也許你可以考慮刪除純Python的需求並使用外部庫 –

+1

如果你想解決任何方程,你將不得不建立自己的庫。對於這個例子,4.5秒也不夠快:D – jamylak

+0

這些問題總是會看起來像'爲y解決y = mx + c? –

回答

26

SymPy怎麼樣?他們的solver看起來像你所需要的。看看他們的源代碼,如果你想自己建立庫...

+2

有趣的是,在問題的所有諷刺評論的幾分鐘內看到這樣的答案:D – naught101

6

使用不同的工具。像Wolfram Alpha,Maple,R,Octave,Matlab或任何其他代數軟件包。

作爲一個初學者,你應該不要試圖解決這樣一個不平凡的問題。

+0

Wolfram Alpha是驚人的。我用它來解決'3 ** x = 4'並得到了滿意的答案。 – Zen

+0

...實際上,這是一個非常容易的; log(3 ** x)== x * log(3)== log(4)so x = log(4)/ log(3)= 1.261859 ... –

7

Python的可能是好的,但它不是神......

有幾種不同的方法進行求解。 SymPy已被提及,如果您正在尋找分析解決方案。

如果你很高興有一個數值解決方案,Numpy有幾個例程可以提供幫助。如果你只對多項式的解決方案感興趣,numpy.roots就可以工作。特別針對您提到的情況:

>>> import numpy 
>>> numpy.roots([2,-6]) 
array([3.0]) 

如需更復雜的表達式,請查看scipy.fsolve。

無論採用哪種方式,您都無法使用庫進行轉義。

6

如果你只是想解決集極其有限的正整數m, c, y方程mx + c = y的,那麼這將做到:

import re 
def solve_linear_equation (equ): 
    """ 
    Given an input string of the format "3x+2=6", solves for x. 
    The format must be as shown - no whitespace, no decimal numbers, 
    no negative numbers. 
    """ 
    match = re.match(r"(\d+)x\+(\d+)=(\d+)", equ) 
    m, c, y = match.groups() 
    m, c, y = float(m), float(c), float(y) # Convert from strings to numbers 
    x = (y-c)/m 
    print ("x = %f" % x) 

一些測試:

>>> solve_linear_equation("2x+4=12") 
x = 4.000000 
>>> solve_linear_equation("123x+456=789") 
x = 2.707317 
>>> 

如果你想認識並解決任意等式,如sin(x) + e^(i*pi*x) = 1,那麼你將需要實現某種符號數學工程師ne,類似於maxima,Mathematica,MATLAB的solve()或符號工具箱等。作爲新手,這超出了你的肯定。

11

解決此問題的方法有兩種:數字和符號。

要解決它的數值問題,你必須首先將它編碼爲「可運行」功能 - 將值存入,獲取值。例如,

def my_function(x): 
    return 2*x + 6 

它很可能解析一個字符串來自動創建這樣一個函數;假設你將2x + 6解析爲列表,​​(其中列表索引對應於x的冪 - 因此6 * x^0 + 2 * x^1)。然後:

def makePoly(arr): 
    def fn(x): 
     return sum(c*x**p for p,c in enumerate(arr)) 
    return fn 

my_func = makePoly([6, 2]) 
my_func(3) # returns 12 

然後,您需要另一個函數,它反覆插頭的x值到您的函數,着眼於結果,它想找到什麼區別,並調整它的x值(希望)減少區別。

def dx(fn, x, delta=0.001): 
    return (fn(x+delta) - fn(x))/delta 

def solve(fn, value, x=0.5, maxtries=1000, maxerr=0.00001): 
    for tries in xrange(maxtries): 
     err = fn(x) - value 
     if abs(err) < maxerr: 
      return x 
     slope = dx(fn, x) 
     x -= err/slope 
    raise ValueError('no solution found') 

有很多在這裏潛在的問題 - 找到一個很好的起點x值,假設該功能實際上有一個解決方案(即有沒有真正值的答案爲x^2 + 2 = 0),擊球計算精度等的限制,但在這種情況下,誤差最小化功能是合適的,我們得到了一個不錯的結果:

solve(my_func, 16) # returns (x =) 5.000000000000496 

注意,該解決方案是不是絕,究竟正確的。如果你需要它是完美的,或者如果你想嘗試解析方程族的解決方案,你必須轉向更復雜的野獸:一個象徵性的解決方案。

像Mathematica或Maple這樣的符號求解器是一個專家系統,它有許多關於代數,微積分等內置規則(「知識」);它「知道」sin的導數是cos,kx^p的導數是kpx ^(p-1),等等。當你給它一個等式時,它試圖找到一個路徑,一組規則應用程序,從它的位置(等式)到你想要的位置(等式的最簡單可能的形式,希望是解決方案) 。

你的例子方程很簡單;一個象徵性的解決方案可能是:

=> LHS([6, 2]) RHS([16]) 

# rule: pull all coefficients into LHS 
LHS, RHS = [lh-rh for lh,rh in izip_longest(LHS, RHS, 0)], [0] 

=> LHS([-10,2]) RHS([0]) 

# rule: solve first-degree poly 
if RHS==[0] and len(LHS)==2: 
    LHS, RHS = [0,1], [-LHS[0]/LHS[1]] 

=> LHS([0,1]) RHS([5]) 

,並有您的解決方案:X = 5

我希望這給這個想法的味道;實施細節(找到一套好的,完整的規則並決定何時應用每個規則)很容易耗費許多人工年的努力。