2012-05-08 44 views
16

Hãy nói rằng tôi có một phương trình:Làm thế nào tôi có thể giải các phương trình bằng Python?

2x + 6 = 12

Với đại số chúng ta có thể thấy rằng x = 3. Làm thế nào tôi có thể tạo một chương trình bằng Python có thể giải quyết cho x? Tôi mới lập trình và tôi đã xem eval()exec() nhưng tôi không thể tìm ra cách làm cho họ làm những gì tôi muốn. Tôi không muốn sử dụng thư viện bên ngoài (ví dụ: SAGE), tôi muốn thực hiện điều này chỉ bằng Python đơn giản.

+7

Tôi muốn một chiếc xe hơi 0 đến 60 trong 4,5 giây và nhận được 45 MPG. Có lẽ bạn có thể xem xét loại bỏ yêu cầu cho Python đơn giản và sử dụng thư viện bên ngoài –

+1

Nếu bạn muốn giải quyết bất kỳ phương trình nào, bạn sẽ phải xây dựng thư viện của riêng mình. Ngoài ra 4,5 giây không đủ nhanh cho ví dụ này: D – jamylak

+0

Các vấn đề có luôn luôn giống như 'giải quyết y = mx + c đối với x' không? –

Trả lời

26

Làm thế nào về SymPy? solver của chúng trông giống như những gì bạn cần. Hãy xem mã nguồn của họ nếu bạn muốn tự xây dựng thư viện…

+2

Vui khi thấy câu trả lời như thế này trong vòng vài phút của tất cả các nhận xét về câu hỏi: D – naught101

6

Sử dụng công cụ khác. Một cái gì đó như Wolfram Alpha, Maple, R, Octave, Matlab hoặc bất kỳ gói phần mềm đại số nào khác.

Là người mới bắt đầu, có lẽ bạn không nên cố gắng giải quyết một vấn đề không tầm thường như vậy.

+0

Wolfram Alpha thật tuyệt vời. Tôi sử dụng nó để giải quyết '3 ** x = 4' và có một câu trả lời thỏa mãn. – Zen

+0

... thực sự, đó là một điều khá dễ dàng; log (3 ** x) == x * log (3) == log (4) vì vậy x = log (4)/log (3) = 1.261859 ... –

7

Python có thể tốt, nhưng không phải là Thiên Chúa ...

Có một vài cách khác nhau để giải phương trình. SymPy đã được đề cập, nếu bạn đang tìm kiếm các giải pháp phân tích.

Nếu bạn hài lòng khi chỉ có một giải pháp số, Numpy có một vài thủ tục có thể trợ giúp. Nếu bạn chỉ quan tâm đến các giải pháp cho đa thức, numpy.roots sẽ hoạt động. Cụ thể cho trường hợp bạn đã đề cập:

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

Để có biểu thức phức tạp hơn, hãy xem scipy.fsolve.

Dù bằng cách nào, bạn không thể thoát bằng thư viện.

6

Nếu bạn chỉ muốn giải quyết bộ cực kỳ hạn chế về phương trình mx + c = y cho số nguyên dương m, c, y, thì điều này sẽ làm:

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) 

Một số xét nghiệm:

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

Nếu bạn muốn nhận biết và giải quyết tùy ý phương trình, như sin(x) + e^(i*pi*x) = 1, sau đó bạn sẽ cần triển khai một số loại toán học biểu tượng ne, tương tự như maxima, Mathematica, MATLAB's solve() hoặc Hộp công cụ mang tính biểu tượng, v.v ... Như một người mới, điều này nằm ngoài ken của bạn.

11

Có hai cách để tiếp cận vấn đề này: số lượng và biểu tượng.

Để giải quyết nó bằng số, trước tiên bạn phải mã hóa nó dưới dạng hàm "runnable" - hãy gắn giá trị vào, lấy giá trị. Ví dụ:

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

Có thể phân tích chuỗi để tự động tạo chức năng như vậy; giả sử bạn phân tích cú pháp 2x + 6 thành danh sách, [6, 2] (trong đó chỉ mục danh sách tương ứng với sức mạnh của x - vì vậy 6 * x^0 + 2 * x^1).Sau đó:

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 

Sau đó bạn cần một chức năng mà nhiều lần cắm một x-giá trị vào chức năng của bạn, nhìn vào sự khác biệt giữa kết quả và những gì nó muốn tìm, và tweaks x-giá trị của nó (hy vọng) giảm thiểu Sự khác biệt.

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') 

Có rất nhiều vấn đề tiềm ẩn ở đây - tìm kiếm một khởi đầu x-giá trị tốt, giả định rằng chức năng thực sự có một giải pháp (tức là không có câu trả lời thực có giá trị đến x^2 + 2 = 0), đánh các giới hạn của độ chính xác tính toán, vv Tuy nhiên, trong trường hợp này, hàm lỗi giảm thiểu phù hợp và chúng tôi có được một kết quả tốt:

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

Lưu ý rằng giải pháp này không phải là hoàn toàn, chính xác đúng. Nếu bạn cần nó để được hoàn hảo, hoặc nếu bạn muốn thử giải quyết các gia đình của phương trình phân tích, bạn phải chuyển sang một con thú phức tạp hơn: một người giải quyết tượng trưng.

Bộ giải mã tượng trưng, ​​như Mathematica hoặc Maple, là một hệ thống chuyên gia có rất nhiều quy tắc (kiến thức) tích hợp sẵn về đại số, phép tính, v.v. nó "biết" rằng đạo hàm của sin là cos, rằng đạo hàm của kx^p là kpx^(p-1), và vân vân. Khi bạn cho nó một phương trình, nó cố gắng tìm một đường dẫn, một tập hợp các ứng dụng quy tắc, từ đó nó (phương trình) đến nơi bạn muốn trở thành (dạng đơn giản nhất có thể của phương trình, hy vọng là giải pháp) .

Phương trình ví dụ của bạn khá đơn giản; một giải pháp mang tính biểu tượng có thể trông giống như:

=> 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]) 

và có giải pháp của bạn: x = 5.

Tôi hy vọng điều này sẽ cho hương vị của các ý tưởng; các chi tiết thực hiện (tìm một bộ quy tắc tốt, đầy đủ và quyết định khi nào mỗi quy tắc nên được áp dụng) có thể dễ dàng tiêu thụ nhiều nỗ lực của con người.