您的位置:首页 > 编程语言 > Python开发

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

2017-01-05 13:48 363 查看
#!/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 

    

        
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  四则运算 python
相关文章推荐