【问题标题】:How can I solve equations in Python? [closed]如何在 Python 中求解方程? [关闭]
【发布时间】:2012-05-17 00:21:47
【问题描述】:

假设我有一个方程式:

2x + 6 = 12

通过代数我们可以看到x = 3。如何用 Python 编写一个可以解决x 的程序?我是编程新手,我查看了eval()exec(),但我不知道如何让他们做我想做的事。我不想使用外部库(例如 SAGE),我只想用普通的 Python 来完成。

【问题讨论】:

  • 如果你想解任何方程,你必须建立自己的库。对于这个例子来说,4.5 秒也不够快:D
  • 问题总是看起来像solve y = mx + c for x
  • @MikePennington:如果他只想允许一组非常有限的方程,那是完全可行的。当然,在抽象的情况下,您必须构建自己的符号数学引擎 a-la maximaMathematica,但我认为这不是目的。

标签: python calculator equation


【解决方案1】:

SymPy 怎么样?他们的solver 看起来像你需要的。如果您想自己构建库,请查看他们的源代码......

【讨论】:

  • 很高兴在几分钟内看到这样的答案:D
【解决方案2】:

使用不同的工具。类似Wolfram AlphaMapleROctaveMatlab 或任何其他代数软件包。

作为一个初学者,你可能不应该尝试解决这样一个不重要的问题。

【讨论】:

    【解决方案3】:

    Python 可能很好,但它不是上帝……

    解方程有几种不同的方法。如果您正在寻找分析解决方案,SymPy 已经被提及。

    如果您乐于获得数值解,Numpy 有一些可以提供帮助的例程。如果您只对多项式的解决方案感兴趣,那么 numpy.roots 将起作用。特别针对您提到的案例:

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

    对于更复杂的表达式,请查看 scipy.fsolve。

    无论哪种方式,您都无法使用库来逃避。

    【讨论】:

    • 除非你知道你的数值方法的核心,否则你不能,无论如何这可能会导致比一些强大的库更糟糕的结果
    【解决方案4】:

    如果您只想解决正整数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,那么您需要实现某种符号数学引擎,类似于maximaMathematica、MATLAB 的@ 987654328@或Symbolic Toolbox等。作为新手,这超出了你的理解。

    【讨论】:

      【解决方案5】:

      有两种方法可以解决这个问题:数字和符号。

      要以数字方式解决它,您必须首先将其编码为“可运行”函数 - 插入一个值,取出一个值。例如,

      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 的导数是 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。

      我希望这能给这个想法带来味道;实施的细节(找到一套好的、完整的规则并决定何时应用每条规则)很容易消耗很多人年的努力。

      【讨论】:

        猜你喜欢
        • 2021-12-22
        • 1970-01-01
        • 1970-01-01
        • 2019-07-25
        • 1970-01-01
        • 2011-11-01
        • 2022-07-06
        • 1970-01-01
        相关资源
        最近更新 更多