有没有办法解决像
这样的简单线性方程 -x+3 = x+5
使用二分搜索?或任何其他数值方法?
背景:
我的问题是因为我想解决像"2x+5-(3x+2)=x+5"
这样的方程式。可能的运算符有:*
,-
,+
和brackets
。
我首先考虑将其转换为中间符号两侧的中缀表示法,然后执行某种二分法搜索。
您如何看待这种方法?我应该在接受采访的不到40分钟内解决这个问题。
答案 0 :(得分:1)
编写一个简单的解析器并不难解释$ -x + 3 - (x + 5)= 0 $或任何其他类似的表达式代数为$ a * x + b = 0 $的累积常数$ a $和$ b $。然后,人们可以轻松地将精确解决方案计算为$ x = -b / a $。
如果你真的想要一个数值方法,请注意双方都描述了他们自己的线性函数图,即左边的$ y_l = -x_l + 3 $和右边的$ y_r = x_r + 5 $。因此,找到该等式的解决方案与找到两个函数的交叉点相同。因此,您可以从任何值$ x = x_l = x_r $开始,并评估双方以获得相应的左右$ y $ -values $ y_l $和$ y_r $。如果他们的差异是0美元,那么你找到了一个解决方案(运气的唯一交叉点,或者两条线相等,如$ 2x = 2x $)。否则,请检查,例如,位置$ x + 1 $。如果新差值$ y_l - y_r $与之前不变,则两条线都是并行的(例如$ 2x = 2x + 7 $)。否则差异越来越远或接近0(从正面或负面)。所以,现在你已经拥有了你需要的所有数据来测试更多点$ x $(例如,如果你最初寻找一些$ x $来实现积极的$ y $ -difference和另一个$ x $那么你需要二元搜索方式实现负$ $ $差异,然后在它们之间运行二进制搜索)以接近差$ y_l - y_r $为$ 0 $的$ x $ -value。 (当然,您也可以再次以代数方式计算解决方案,因为在两个位置评估线条可以为您提供准确计算交点所需的所有信息。)
因此,数值方法在这里非常荒谬,但它激发了这种算法的思维方式。
答案 1 :(得分:0)
你真的需要用数值方法解决它吗?我很确定你可以,但解析表达式解析它并不是那么难。我的意思是,如果它确实是一个线性方程式,那么在方程式减少时,发现x的系数和自由项是一个问题。在这个问题的26分钟内,我做了一个简单的解析器,手工完成:
import re, sys, json
TOKENS = {
'FREE': '[0-9]+',
'XTERM': '[0-9]*x',
'ADD': '\+',
'SUB': '-',
'POW': '\^',
'MUL': '\*',
'EQL': '=',
'LPAREN': '\(',
'RPAREN': '\)',
'EOF': '$'
}
class Token:
EOF = lambda p: Token('EOF', '', p)
def __init__(self, name, raw, position):
self.name = name
self.image = raw.strip()
self.raw = raw
self.position = position
class Expr:
def __init__(self, x, c):
self.x = x
self.c = c
def add(self, e):
return Expr(self.x + e.x, self.c + e.c)
def sub(self, e):
return Expr(self.x - e.x, self.c - e.c)
def mul(self, e):
return Expr(self.x * e.c + e.x * self.c, self.c * e.c)
def neg(self):
return Expr(-self.x, -self.c)
class Scanner:
def __init__(self, expr):
self.expr = expr
self.position = 0
def match(self, name):
match = re.match('^\s*'+TOKENS[name], self.expr[self.position:])
return Token(name, match.group(), self.position) if match else None
def peek(self, *allowed):
for match in map(self.match, allowed):
if match: return match
def next(self, *allowed):
token = self.peek(*TOKENS)
self.position += len(token.raw)
return token
def maybe(self, *allowed):
if self.peek(*allowed):
return self.next(*allowed)
def following(self, value, *allowed):
self.next(*allowed)
return value
def expect(self, **actions):
token = self.next(*actions.keys())
return actions[token.name](token)
def evaluate(expr, variables={}):
tokens = Scanner(expr)
def Binary(higher, **ops):
e = higher()
while tokens.peek(*ops):
e = ops[tokens.next(*ops).name](e, higher())
return e
def Equation():
left = Add()
tokens.next('EQL')
right = Add()
return left.sub(right)
def Add(): return Binary(Mul, ADD=Expr.add, SUB=Expr.sub)
def Mul(): return Binary(Neg, MUL=Expr.mul)
def Neg():
return Neg().neg() if tokens.maybe('SUB') else Primary()
def Primary():
return tokens.expect(
FREE = lambda x: Expr(0, float(x.image)),
XTERM = lambda x: Expr(float(x.image[:-1] or 1), 0),
LPAREN = lambda x: tokens.following(Add(), 'RPAREN'))
expr = tokens.following(Equation(), 'EOF')
return -expr.c / float(expr.x)
print evaluate('2+2 = x')
print evaluate('-x+3 = x+5')
print evaluate('2x+5-(3x+2)=x+5')
答案 2 :(得分:0)
如果你需要二元搜索,那么它很容易实现(但它太可悲了,哈哈)
对于二进制搜索中的当前x
,解析并计算等式的左右部分。然后,根据left > right
表达式更改搜索范围。
如果将所有内容移动到左侧部分(右侧部分现在等于0),如果x < 0
将所有内容与-1
相乘,则很容易获得。然后,很明显,如果当前x
的表达式为expr > 0
,那么您需要使x
更小,否则 - 更大。
但是......你为什么需要那个? = d
答案 3 :(得分:-1)
首先,您的问题必须与Solving Binary Tree相关。您可以使用的方法是构造二进制尝试,将根运算符设置为具有最高优先级的运算符,遵循较低优先级运算符和操作是叶节点。您可以在solving equation中了解此方法。