用Python3实现表达式求值

 我来答
就烦条0o
2016-07-06 · 知道合伙人软件行家
就烦条0o
知道合伙人软件行家
采纳数:33315 获赞数:46492
从事多年系统运维,喜欢编写各种小程序和脚本。

向TA提问 私信TA
展开全部

代码如下:

# -*- coding: utf-8 -*-

#################################
# @Author:            Maples7
# @LaunchTime:        2016/2/24 12:32:38
# @FileName:        main
# @Email:            maples7@163.com
# @Function:
#                   
#       A Python Calculator for Operator +-*/()^
#
#################################

from sys import argv
from decimal import *

def delBlank(str):
    """
    Delete all blanks in the str
    """
    ans = ""
    for e in str:
        if e != " ":
            ans += e
    return ans

def precede(a, b):
    """
    Compare the prior of operator a and b
    """
    # the prior of operator
    prior = (
        #   '+'  '-'  '*'  '/'  '('  ')'  '^'  '#'
           ('>', '>', '<', '<', '<', '>', '<', '>'), # '+'
           ('>', '>', '<', '<', '<', '>', '<', '>'), # '-'
           ('>', '>', '>', '>', '<', '>', '<', '>'), # '*'
           ('>', '>', '>', '>', '<', '>', '<', '>'), # '/'
           ('<', '<', '<', '<', '<', '=', '<', ' '), # '('
           ('>', '>', '>', '>', ' ', '>', '>', '>'), # ')'
           ('>', '>', '>', '>', '<', '>', '>', '>'), # '^'
           ('<', '<', '<', '<', '<', ' ', '<', '=')  # '#'
        )

    # operator to index of prior[8][8]
    char2num = {
        '+': 0,
        '-': 1,
        '*': 2,
        '/': 3,
        '(': 4,
        ')': 5,
        '^': 6,
        '#': 7
        }

    return prior[char2num[a]][char2num[b]]

def operate(a, b, operator):
    """
    Operate [a operator b]
    """
    if operator == '+':
        ans = a + b
    elif operator == '-':
        ans = a - b
    elif operator == '*':
        ans = a * b
    elif operator == '/':
        if b == 0:
            ans = "VALUE ERROR"
        else:
            ans = a / b
    elif operator == '^':
        if a == 0 and b == 0:
            ans = "VALUE ERROR"
        else:
            ans = a ** b

    return ans

def calc(exp):
    """
    Calculate the ans of exp
    """
    exp += '#'
    operSet = "+-*/^()#"
    stackOfOperator, stackOfNum = ['#'], []
    pos, ans, index, length = 0, 0, 0, len(exp)
    while index < length:
        e = exp[index]
        if e in operSet:
            # calc according to the prior
            topOperator = stackOfOperator.pop()
            compare = precede(topOperator, e)
            if compare == '>':
                try:
                    b = stackOfNum.pop()
                    a = stackOfNum.pop()
                except:
                    return "FORMAT ERROR"
                ans = operate(a, b, topOperator)
                if ans == "VALUE ERROR":
                    return ans
                else:
                    stackOfNum.append(ans)
            elif compare == '<':
                stackOfOperator.append(topOperator)
                stackOfOperator.append(e)
                index += 1
            elif compare == '=':
                index += 1
            elif compare == ' ':
                return "FORMAT ERROR"
        else:
            # get the next num
            pos = index
            while not exp[index] in operSet:
                index += 1
            temp = exp[pos:index]

            # delete all 0 of float in the end
            last = index - 1
            if '.' in temp:
                while exp[last] == '0':
                    last -= 1
                temp = exp[pos:last + 1]

            try:
                temp = Decimal(temp)
            except:
                return "INPUT ERROR"
            stackOfNum.append(temp)

    if len(stackOfNum) == 1 and stackOfOperator == []:
        return stackOfNum.pop()
    else:
        return "INPUT ERROR"

if __name__ == "__main__":
    # get the exp
    exp = argv[1]

    # set the precision
    getcontext().prec = 10

    # delete blanks
    exp = delBlank(exp)

    # calc and print the ans
    ans = calc(exp)
    print(ans)
推荐律师服务: 若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询

为你推荐:

下载百度知道APP,抢鲜体验
使用百度知道APP,立即抢鲜体验。你的手机镜头里或许有别人想知道的答案。
扫描二维码下载
×

类别

我们会通过消息、邮箱等方式尽快将举报结果通知您。

说明

0/200

提交
取消

辅 助

模 式