练习python写了一个四则运算程序,支持乘方和“.3"这种格式

来源:互联网 发布:诺基亚n97的软件 编辑:程序博客网 时间:2024/06/08 06:31
#!/usr/bin/python
#coding=utf-8


# 本程序由用户输入一个表达式字符串,然后计算这个表达式的值
# 表达式是一个四则运算表达式,可以包含^操作符

# 注意:乘方用^运算符,支持".3"这种表示小数的形式。负数需要用括号扩起来

# 思路:利用栈的方法,先将表达式从中缀表达式转换成后缀表达式,再进行计算



def isNum(value):
    try:
        value+1
    except TypeError:
        return False
    else:
        return True
    
def cal(strexpp):
    ''' 本函数由一个四则运算表达式字符串计算表达式的值
    strexpr为一个四则运算表达式,如果这个表达式正确,则函数返回这个表达式的值,否则返回NULL'''


    seqLegalChar=('+','-','*','/','(',')','^','1','2','3','4','5','6','7','8','9','0','.')  #表达式中合法的字符集


    seqOpr=seqLegalChar[0:7]                   #运算符序列
    seqOpa=seqLegalChar[7:18]                   #操作数序列


    # 表达式为空,则返回Null
    if len(strexpp)==0: return Null
    
    #去掉字符串中的空格
    strexpr=strexpp.replace(' ','')
    
    # 表达式包含不合法的支付,则返回Null
    for ch in strexpr:
        if ch not in seqLegalChar: 
            return Null


    # 将表达式变成一个数字和符号的序列
    numstart=-1                                  #标识数字的起始位置为numstart+1
    seqExpr=[]                                  #表达式序列
    for i in range(0,len(strexpr)):             #将表达式的数字和符号依次输出到序列
        #本位置指向的是一个操作数,
        if (strexpr[i] in seqOpa):                             
            if numstart<0:                      #如果numstart小于0,使numstart指向本位置数字开始的地方
                numstart=i
            if i==len(strexpr)-1:               #已读取到表达式最后一个字符,将数字转换后入列
                seqExpr.append(float(strexpr[numstart:len(strexpp)]))
            continue                                
        
        #本次读取的字符是一个符号
        if numstart>=0:                 #如果numstart大于0,则说明numstart与本位置之间是数字,需要提取数字。如果numstart==-1,则表明中间都是符号
            seqExpr.append(float(strexpr[numstart:i]))  #中间是数字,将数字转换后输出到序列
        seqExpr.append(strexpr[i])          #将本次符号输出到序列
        numstart=-1                          #将numstart指针修改为本次位置
    
    #将中缀表达式转换成为后缀表达式
    seqPosfix=[]                                #后缀表达式序列,完成后seqPosfix中即为后缀表达式
    stkOpra=[]                                  #转换中所需要的符号栈
    for op in seqExpr:
        if isNum(op):                #如果是数字,则直接输出到后缀表达式序列
            seqPosfix.append(op)
            continue
        if not stkOpra:                   #如果符号栈为空,则直接压入第一个符号
            stkOpra.append(op)
            continue
        if op ==')':                            #如果是')',需要匹配以前的'(',栈顶元素依次出栈输出,知道'('为止
            while stkOpra[len(stkOpra)-1]!='(':
                seqPosfix.append(stkOpra.pop())       #将'('弹出
            stkOpra.pop()
        elif op in ['+','-']:               #如果是'+'或者'-',优先级最低
            while (stkOpra and (stkOpra[len(stkOpra)-1]!='(')):
                seqPosfix.append(stkOpra.pop())
            stkOpra.append(op)
        elif op in ['*','/']:               #如果是'*','/',栈顶是'*','/','^'则弹出,否则入栈
            while (stkOpra and (stkOpra[len(stkOpra)-1]=='^' )):
                seqPosfix.append(stkOpra.pop())
            stkOpra.append(op)
        elif op in ['^','(']:               #如果是'^'和'(',优先级最高,则直接入栈
            stkOpra.append(op)
    while stkOpra:                          #到最后如果符号栈不为空,则将符号栈的符号全部出栈
        seqPosfix.append(stkOpra.pop())


    #根据后缀表达式seqPosfix计算值
    stkNumb=[]                              #装载操作数和值的栈
    for op in seqPosfix:
        if isNum(op):
            stkNumb.append(op)     #如果是数字,直接进栈
            continue
        p1=stkNumb.pop()            #弹出两个操作数
        p2=stkNumb.pop()        
        if op=='^':                 #根据运算符计算操作数的值
            p=p2**p1
        elif op=='*':
            p=p2*p1
        elif op=='/':
            p=p2/p1
        elif op=='+':
            p=p2+p1
        elif op=='-':
            p=p2-p1
        stkNumb.append(p)           #将计算结果入栈
    
    return stkNumb.pop()            #最后的结果


expr=raw_input("请输入一个四则运算表达式(负数需要用括号扩起来,乘方用'^'运算符):")
res=cal(expr)
if not res:
    print "你输入的四则运算表达式包含有不正确的字符,请检查后重新输入。"
else:
    print "结果为:%f" % res 
    
        



0 0
原创粉丝点击