在一个变量中求解线性方程

时间:2013-04-29 07:30:51

标签: c++ python algorithm linear-algebra

在作为函数的字符串输入给出的一个变量中求解线性方程的最有效算法是什么?例如,对于输入字符串:

  

“x + 9 - 2 - 4 + x = - x + 5 - 1 + 3 - x”

输出应为1.

我正在考虑使用堆栈并将每个字符串标记推送到它上面,因为我在字符串中遇到空格。如果输入是波兰表示法,那么从堆栈中弹出数字以获得结果会更容易,但我不确定采取何种方法。

这是一个面试问题。

4 个答案:

答案 0 :(得分:11)

一旦你计算出等式a中的系数ba * x + b = 0,解决线性方程是(我希望)非常容易。

因此,问题的难点在于解析表达式并“评估”它以找到系数。您的示例表达式非常简单,它仅使用运算符一元-,二进制-,二进制+。还有=,你可以专门处理。

问题是否也应该处理涉及二进制*/或括号的表达式,这一点尚不清楚。我想知道面试问题是否有意:

  • 让你写一些简单的代码,或者
  • 让你在写任何东西之前询问问题的实际范围。

两者都是重要的技能: - )

甚至可能是这个问题:

  • 分离那些有很多编写解析器的经验(他们会尽可能快地解决它们的问题)和那些没有解决方案的人(他们可能会在几分钟内完全解决它,至少没有一些提示)

无论如何,为了满足未来更复杂的要求,解析算术表达式有两种常用的方法:递归下降或Dijkstra的分流码算法。您可以查看这些内容,如果您只需要1.0版中的简单表达式,那么您可以使用简化形式的Dijkstra算法。然后,一旦解析了表达式,就需要对其进行求值:使用x中的线性表达式值并将=解释为具有最低可能优先级的运算符,即“减去”。结果是x中的线性表达式等于0

如果你不需要复杂的表达式,那么一旦你对它进行了标记,就可以从左到右直接评估这个简单的例子[*]:

x
x + 9
// set the "we've found minus sign" bit to negate the first thing that follows
x + 7 // and clear the negative bit
x + 3
2 * x + 3
// set the "we've found the equals sign" bit to negate everything that follows
3 * x + 3
3 * x - 2
3 * x - 1
3 * x - 4
4 * x - 4

最后,将a * x + b = 0解析为x = - b/a

[*]示例标记化代码,在Python中:

acc = None
for idx, ch in enumerate(input):
    if ch in '1234567890':
        if acc is None: acc = 0
        acc = 10 * acc + int(ch)
        continue
    if acc != None:
        yield acc
        acc = None
    if ch in '+-=x':
        yield ch
    elif ch == ' ':
        pass
    else:
        raise ValueError('illegal character "%s" at %d' % (ch, idx))

备选示例令牌化代码,也在Python中,假设在示例中将始终存在令牌之间的空格。这会将令牌验证留给解析器:

return input.split()

答案 1 :(得分:1)

确定一些可用于解决此问题的简单伪代码

 function(stinrgToParse){
      arrayoftokens = stringToParse.match(RegexMatching);
      foreach(arrayoftokens as token)
      {
         //now step through the tokens and determine what they are
         //and store the neccesary information.
      }
      //Use the above information to do the arithmetic.
      //count the number of times a variable appears positive and negative
      //do the arithmetic.
      //add up the numbers both positive and negative. 
      //return the result.
 }

答案 2 :(得分:1)

首先要解析字符串,以识别各种标记(数字,变量和运算符),以便通过赋予运算符适当的优先级来形成表达式树。

正则表达式可以提供帮助,但这不是唯一的方法(像boost :: spirit这样的语法解析器也很好,你甚至可以运行自己的:它的所有“查找和追索”)。

然后可以操作树,减少执行处理常量的操作的节点,并通过对变量相关操作进行分组,相应地执行它们。

这将以递归方式进行,直到您保留变量相关节点和常量节点。

在解决方案的基础上进行简单计算。

它们基本上与导致生成解释器或编译器的原理相同。

答案 3 :(得分:1)

考虑:

from operator import add, sub
def ab(expr):
    a, b, op = 0, 0, add
    for t in expr.split():
        if   t == '+': op = add
        elif t == '-': op = sub
        elif t == 'x': a = op(a, 1)
        else         : b = op(b, int(t))
    return a, b

给定1 + x - 2 - x...之类的表达式,将其转换为规范形式ax+b并返回一对系数(a,b)

现在,让我们从等式的两个部分获得系数:

le, ri = equation.split('=')    
a1, b1 = ab(le)
a2, b2 = ab(ri)    

最后解决了微不足道的等式a1*x + b1 = a2*x + b2

x = (b2 - b1) / (a1 - a2)

当然,这只解决了这个特殊的例子,没有运算符优先级或括号。为了支持后者,你需要一个解析器,可以使用一个递归下降的解析器,这样可以简化手工编码。