2012-05-08 4 views
16

Скажем, у меня есть уравнение:Как я могу решить уравнения в Python?

2x + 6 = 12

С алгеброй мы можем видеть, что x = 3. Как я могу сделать программу на Python, которая может решить для x? Я новичок в программировании, и я посмотрел на eval() и exec(), но я не могу понять, как заставить их делать то, что я хочу. Я не хочу использовать внешние библиотеки (например, SAGE), я хочу сделать это просто на Python.

+7

Мне нужен автомобиль, который делает от 0 до 60 за 4,5 секунды и получает 45 MPG. Возможно, вы могли бы рассмотреть возможность удаления требования для простого Python и использования внешних библиотек. –

+1

Если вы хотите решить какое-либо уравнение, вам придется создать свою собственную библиотеку. Кроме того, для этого примера не хватает 4,5 секунд: D – jamylak

+0

Являются ли проблемы всегда похожими на 'solve y = mx + c for x'? –

ответ

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), так что 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

Если вы хотите, чтобы решить крайне ограниченный набор уравнений mx + c = y для положительного целого числа m, 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, тогда вам понадобится реализовать какую-то символическую математику engi ne, аналогично maxima, Mathematica, MATLAB's solve() или Symbolic Toolbox и т. д. Как новичок, это за пределами вашего ken.

11

Существует два подхода к решению этой проблемы: численно и символически.

Чтобы решить эту задачу численно, вы должны сначала закодировать ее как функцию «runnable» - вставить значение в значение, получить значение. Например,

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

Весьма возможно проанализировать строку, чтобы автоматически создать такую ​​функцию; скажем, вы разобрали 2x + 6 в список, [6, 2] (где индекс списка соответствует мощности 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 

Затем понадобится еще одна функция, которая повторно подключается х-значение в вашей функции, смотрит на разницу между результатом и тем, что он хочет найти, и щипки его х-значение (мы надеемся) свести к минимуму разница.

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

Есть много потенциальных проблем здесь - найти хорошую отправную х-значение, предполагая, что функция на самом деле имеет решение (т.е. нет вещественнозначные ответы на х^2 + 2 = 0), ударяя пределы точности вычислений и т.д. Но в этом случае, функция минимизации ошибок подходит, и мы получаем хороший результат:

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

Обратите внимание, что это решение не является абсолютно , точно правильно. Если вам нужно, чтобы это было идеально, или если вы хотите аналитически анализировать решения уравнений, вам нужно обратиться к более сложному зверю: символическому решателю.

Символический решатель, такой как Mathematica или Maple, представляет собой экспертную систему с множеством встроенных правил («знаний») об алгебре, исчислении и т. Д .; он «знает», что производная от sin is 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]) 

и есть ваше решение: х = 5.

Я надеюсь, что это дает аромат идеи; детали реализации (поиск хорошего, полного набора правил и принятие решения о применении каждого правила) могут легко потреблять много человеко-лет усилий.