一元一次方程的解析解(基本字符串处理)

    找工作投简历的时候遇到这样一道题,“如何通过基础的解析字符串的方式去求解一元一次方程,而不通过工具包或者内置函数等计算?”,即输入任意一个一元一次函数(如:"((2x+1)*3+1)+(3+2x)=5x+3+(2x+1)"等等  ),当时觉得有趣,于是想好好做一下~
    最开始的时候想直接从表达式下手,但是由于有括号对优先级的影响,使得考虑的情况实在是比较复杂,于是便想到分别利用两个栈对表达式求解(data栈用来存储数字{'0','1','2','3','4','5','6','7','8','9','x'},operation栈用来存储操作运算符{'+','-','*','/'},对于利用栈计算算术表达式,这篇博客有详细讲解:https://blog.csdn.net/xyh1re/article/details/81634236。而对于计算x解析解而言,为了方便计算,需要将表达式转换为[a,b]**[x0,x1].T的形式(即a表示常数项,b表示一次项),这里又要分几种情况:
    (1)当操作符为{‘+’,‘-’}时,即形如(ax+b),这里经转换得到: np.array([0,a])+np.array([b,0])=np.array([b,a])
    (2)当操作符为{‘*’,‘/’}时,即形如(ax+b)*c,这里经转换得到:np.array([b,a])*np.array([c,c]),注意此时的转换方式有变化(不是np.array([c,0]))。
    详细的代码如下:
 

# 将表达式进行标准化,即[a,b]*(x0,x1).T的形式
# 利用两个栈实现表达式的运算
# operation 保存运算符
# data 保存数字
# 遍历表达式,若为数字则直接入栈data,若为符号分几种情况入栈opration:
#     (1)栈为空
#     (2)栈顶为左括号
#     (3)该符号为左括号
#     (4)该符号优先级高于栈顶符号
# 若符号为右括号,则operation输出栈顶符号,从data输出两个数运算再入栈data,
# 直到栈顶为左括号,然后左括号出栈,若符号优先级低于栈顶元素,则重复计算步骤,
# 直到栈为空或栈顶为左括号。
import numpy as np
number={'0','1','2','3','4','5','6','7','8','9','x'}

def data_process1(string):   #如:5x
    if not isinstance(string,str):
        return string
    a=0
    b=0
    index=-1
    for i in range(len(string)):
        if string[i]=="x":
            index=i
    if index==-1:       # 5
        a=float(string)
        b=0.0
    elif index==0:     # x
        a=0.0
        b=1.0
    elif index==1:     # -x,2x
        if string[0]=="-":
            a=0.0
            b=-1.0
        else:
            a=0.0
            b=float(string[0])
    else:               # 5x
        a=0.0
        b=float(string[:index])
    return np.array([a,b])

def data_process2(string):   #如:5x
    if not isinstance(string,str):
        return string
    a=0
    b=0
    index=-1
    for i in range(len(string)):
        if string[i]=="x":
            index=i
    if index==-1:       # 5
        a=float(string)
        b=float(string)
    elif index==0:     # x
        a=0.0
        b=1.0
    elif index==1:     # -x,2x
        if string[0]=="-":
            a=0.0
            b=-1.0
        else:
            a=0.0
            b=float(string[0])
    else:               # 5x
        a=0.0
        b=float(string[:index])
    return np.array([a,b])

def num_operation(num1,num2,op):
    if op=="+":
        return data_process1(num1)+data_process1(num2)
    if op=="-":
        return data_process1(num1)-data_process1(num2)
    if op=="*":
        return data_process2(num1)*data_process2(num2)
    if op=="/":
        return data_process2(num1)/data_process2(num2)

def caculate(data,operation):
    op=operation.pop()
    num2=data.pop()
    num1=data.pop()
    data.append(num_operation(num1,num2,op))

def function(s):
    data=[]
    operation=[]
    i=0
    while i<len(s):
        if s[i] in number:       #数字直接入栈data
            start=i
            while i+1 <len(s) and s[i+1] in number:
                i+=1
            data.append(s[start:i+1])
        #栈为空或者栈顶为左括号,入栈operation
        elif not operation or operation[-1]=="(":
            operation.append(s[i])
        #该符号为左括号或优先级高于栈顶元素,入栈operation
        elif s[i]=="(" or (s[i] in {"*","/"} and operation[-1] in {"+","-"}):
            operation.append(s[i])
        #该符号为右括号,则operation出栈,data出栈进行计算
        elif s[i]==")":
            while operation[-1]!="(":
                caculate(data,operation)
            operation.pop()
            #该符号优先级不如栈顶高时,operation出栈,data出栈进行计算,直到栈为空或栈顶为左括号
        else:
            while operation and (operation[-1] in {"*","/"} and s[i] in {"+","-"}):
                if operation[-1]=="(":
                    break
                caculate(data,operation)
            operation.append(s[i])
        i+=1

    while operation:
        caculate(data,operation)
    answer=data.pop()
    if isinstance(answer,str):
        return data_process1(answer)
    return answer

if __name__ == '__main__':
    s=input() # 输入合法的表达式,如  1+((2x+3)*2+1)+2x=5x  请勿带引号输入! 只能一次项!
    # s="1+((2x+3)*2+1)+2x=5x"
    left, right = s.split("=")
    lf=function(left)
    rt=function(right)

    result=lf-rt
    answer=-result[0]/result[1]
    print("the answer is:",answer)

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值