Как я могу решить уравнения в Python? - программирование
Подтвердить что ты не робот

Как я могу решить уравнения в Python?

Скажем, у меня есть уравнение:

2x + 6 = 12

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

4b9b3361

Ответ 1

Как насчет SymPy? Их solver выглядит так, как вам нужно. Посмотрите их исходный код, если вы хотите сами построить библиотеку...

Ответ 2

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

Чтобы решить его численно, вы должны сначала закодировать его как функцию "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

Затем вам понадобится другая функция, которая повторно подключает значение 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 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])

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

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

Ответ 3

Python может быть хорошим, но это не Бог...

Существует несколько различных способов решения уравнений. SymPy уже упоминался, если вы ищете аналитические решения.

Если вы счастливы просто иметь численное решение, у Numpy есть несколько подпрограмм, которые могут помочь. Если вас просто интересуют решения для полиномов, numpy.roots будет работать. В частности, для упомянутого вами случая:

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

Для более сложных выражений посмотрите scipy.fsolve.

В любом случае вы не сможете избежать использования библиотеки.

Ответ 4

Используйте другой инструмент. Что-то вроде Wolfram Alpha, Maple, R, Octave, Matlab или любой другой программный пакет алгебры.

Как новичок, вы, вероятно, не должны пытаться решить такую ​​нетривиальную проблему.

Ответ 5

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