用python编写表达式求值_用Python3实现表达式求值

Problem Description yizhen has no girlfriend due to his stupid brain that he even can’t solve a simple arithmetic roblem. Can you help him If you solve it and tell him the result, then he can find his lovers! So beautiful! Input The input

一、题目描述

请用 python3编写一个计算器的控制台程序,支持加减乘除、乘方、括号、小数点,运算符优先级为括号>乘方>乘除>加减,同级别运算按照从左向右的顺序计算。

二、输入描述

数字包括"0123456789",小数点为".",运算符包括:加("+")、减("-")、乘("*")、除("/")、乘方("^",注:不是**!)、括号("()")

需要从命令行参数读入输入,例如提交文件为 main.py,可以用 python3 main.py "1+2-3+4" 的方式进行调用

输入需要支持空格,即 python3 main.py "1     +     2      -     3    +    4" 也需要程序能够正确给出结果

所有测试用例中参与运算的非零运算数的绝对值范围保证在 10^9-10^(-10) 之内, 应该输出运算结果时非零运算结果绝对值也保证在该范围内

三、输出描述

数字需要支持小数点,输出结果取10位有效数字,有效数字位数不足时不能补0

对于不在输入描述内的输入,输出INPUT ERROR

对于格式不合法(例如括号不匹配等)的输入,输出 FORMAT ERROR

对于不符合运算符接收的参数范围(例如除0等)的输入,输出VALUE ERROR

对于2、3、4的情况,输出即可,不能抛出异常

同时满足2、3、4中多个条件时,以序号小的为准

四、样例

输入: 1 + 2 - 3 + 4

输出: 4

输入: 1 + 2 - 3 + 1 / 3

输出: 0.3333333333

输入: 1 + + 2

输出: FORMAT ERROR

输入: 1 / 0

输出: VALUE ERROR

输入: a + 1

输出: INPUT ERROR

【注:此题为TsinghuaX:34100325X 《软件工程》 MOOC 课程 Spring, 2016 Chapter 1 Problem,此文发布时,这门课刚刚在 “学堂在线” 上开课两天】

代码是先看了 http://blog.csdn.net/whos2002110/article/details/19119449 这个网址的。然后 自己记忆写了一份。 本来目的是要学一些 解释器的。虽然也看到一些实现,但是感觉对我有点难度,于是从简单开始学习。 import java.util.ArrayList;import java.

用 Python3 实现,初看一下,首先想到的其实是一种“讨巧”(作弊 >_

大致代码区区几行:

1 from sys import argv

2

3 if __name__ == "__main__":

4 exp = argv[1]

5 print(eval(exp))

即便是考虑到题干中的输出要求做异常处理(try...except)输出相应的错误信息,也就十行左右。

但稍深入就会发现,有些情形还是无法按要求处理的,比如样例 “1 + + 2”,用 eval() 会输出结果 “3” (+2 前的 “+” 被当作正号),而题目要求输出 “FORMAT ERROR”。

没办法,只能老老实实做苦力活儿了。

表达式求值其实是《数据结构》课程里一个基本且重要的问题之一,一般作为 “栈” 的应用来提出。

问题的关键就是需要按照人们通常理解的运算符的优先级来进行计算,而在计算过程中的临时结果则用 栈 来存储。

为此,我们可以首先构造一个 “表” 来存储当不同的运算符 “相遇” 时,它们谁更 “屌” 一些(优先级更高一些)。这样就可以告诉计算机,面对不同的情形,它接下来应该如何来处理。

其次,我们需要构造两个栈,一个运算符栈,一个运算数栈。

运算符栈是为了搞定当某个运算符优先级较低时,暂时先让它呆在栈的底部位置,待它可以 “重见天日” 的那一天(优先级相对较高时),再把它拿出来使用。正确计算完成后,此栈应为空。

运算数栈则是为了按合理的计算顺序存储运算中间结果。正确计算完成后,此栈应只剩下一个数,即为最后的结果。

完整的代码如下:

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

2

3 #################################

4 # @Author: Maples7

5 # @LaunchTime: 2016/2/24 12:32:38

6 # @FileName: main

7 # @Email: maples7@163.com

8 # @Function:

9 #

10 # A Python Calculator for Operator +-*/()^

11 #

12 #################################

13

14 from sys import argv

15 from decimal import *

16

17 def delBlank(str):

18 """

19 Delete all blanks in the str

20 """

21 ans = ""

22 for e in str:

23 if e != " ":

24 ans += e

25 return ans

26

27 def precede(a, b):

28 """

29 Compare the prior of operator a and b

30 """

31 # the prior of operator

32 prior = (

33 # '+' '-' '*' '/' '(' ')' '^' '#'

34 ('>', '>', '', ''), # '+'

35 ('>', '>', '', ''), # '-'

36 ('>', '>', '>', '>', '', ''), # '*'

37 ('>', '>', '>', '>', '', ''), # '/'

38 ('

39 ('>', '>', '>', '>', ' ', '>', '>', '>'), # ')'

40 ('>', '>', '>', '>', '', '>', '>'), # '^'

41 ('

42 )

43

44 # operator to index of prior[8][8]

45 char2num = {

46 '+': 0,

47 '-': 1,

48 '*': 2,

49 '/': 3,

50 '(': 4,

51 ')': 5,

52 '^': 6,

53 '#': 7

54 }

55

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

57

58 def operate(a, b, operator):

59 """

60 Operate [a operator b]

61 """

62 if operator == '+':

63 ans = a + b

64 elif operator == '-':

65 ans = a - b

66 elif operator == '*':

67 ans = a * b

68 elif operator == '/':

69 if b == 0:

70 ans = "VALUE ERROR"

71 else:

72 ans = a / b

73 elif operator == '^':

74 if a == 0 and b == 0:

75 ans = "VALUE ERROR"

76 else:

77 ans = a ** b

78

79 return ans

80

81 def calc(exp):

82 """

83 Calculate the ans of exp

84 """

85 exp += '#'

86 operSet = "+-*/^()#"

87 stackOfOperator, stackOfNum = ['#'], []

88 pos, ans, index, length = 0, 0, 0, len(exp)

89 while index < length:

90 e = exp[index]

91 if e in operSet:

92 # calc according to the prior

93 topOperator = stackOfOperator.pop()

94 compare = precede(topOperator, e)

95 if compare == '>':

96 try:

97 b = stackOfNum.pop()

98 a = stackOfNum.pop()

99 except:

100 return "FORMAT ERROR"

101 ans = operate(a, b, topOperator)

102 if ans == "VALUE ERROR":

103 return ans

104 else:

105 stackOfNum.append(ans)

106 elif compare == '

107 stackOfOperator.append(topOperator)

108 stackOfOperator.append(e)

109 index += 1

110 elif compare == '=':

111 index += 1

112 elif compare == ' ':

113 return "FORMAT ERROR"

114 else:

115 # get the next num

116 pos = index

117 while not exp[index] in operSet:

118 index += 1

119 temp = exp[pos:index]

120

121 # delete all 0 of float in the end

122 last = index - 1

123 if '.' in temp:

124 while exp[last] == '0':

125 last -= 1

126 temp = exp[pos:last + 1]

127

128 try:

129 temp = Decimal(temp)

130 except:

131 return "INPUT ERROR"

132 stackOfNum.append(temp)

133

134 if len(stackOfNum) == 1 and stackOfOperator == []:

135 return stackOfNum.pop()

136 else:

137 return "INPUT ERROR"

138

139 if __name__ == "__main__":

140 # get the exp

141 exp = argv[1]

142

143 # set the precision

144 getcontext().prec = 10

145

146 # delete blanks

147 exp = delBlank(exp)

148

149 # calc and print the ans

150 ans = calc(exp)

151 print(ans)

其中需要稍微注意的细节有:

1. 表达式处理前,前后都插入一个 '#' 作为一个特殊的运算符,这样做是为了方便统一处理,即不用再去特别判断表达式是否已经结束(从而引发一系列边界问题导致代码冗长复杂,这种处理也可称之为 “哨兵” 技巧)。如果最后两个运算符相遇则说明表达式处理完毕,这个运算符的优先级也是最低的(在 prior 表中也有体现)。

2. 输出要求比较复杂,抛去错误信息输出不说(只能具体情况具体分析),不能输出多余的0,折腾了一会儿最后发现用高精度的 Decimal 可以完美满足题目要求。

3. 由于不能输出多余的0,所以在带有小数部分的数字 “录入” 时(代码115-132行),就要把一些多余的0提前去掉(代码121-126行),比如 2.0 这样的情况。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/258682.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

the first day

开博第一天&#xff0c;从此记录我生活学习的点滴&#xff0c;加油转载于:https://www.cnblogs.com/fkissx/p/3702132.html

驱动-问题解决

今天在网上买了一个二手的电脑&#xff0c;拿回来以后&#xff0c;发现有点问题&#xff0c;一个问题就是 1.usb插上U盘以后没有反应 解决方法&#xff1a; 尝试一、直接在网上下载了一个360驱动大师&#xff0c;更新了一下驱动&#xff0c;没有解决 尝试二、在网上下载了一个驱…

Swift 学习- 02 -- 基础部分2

class NamedShape{ var numberOfSides: Int 0 var name: String init(name: String) { self.name name } func simpleDecription() -> String { return "A shape with \(numberOfSides) \(name) sides" } } // 除了储存简单的属性之外,属性可以有 getter 和 set…

R-CNN detection 运行问题及办法

运行caffe官方提供的jupyter 的rcnn detection&#xff0c;总是出现各种问题。先将问题及方法汇集在此&#xff1a; 1. Selective Search 的安装问题 按照官网&#xff0c;我下载了selective_search_ijcv_with_python&#xff0c;但是在我的linux matlab2017a上总是出现问题&…

python怎么用lambda和map函数_Python之lambda匿名函数及map和filter的用法

现有两个元组((a),(b)),((c),(d))&#xff0c;请使用python中匿名函数生成列表[{a:c},{b:d}]t1 ((a), (c))t2 ((b), (d))print(list(map(lambda t: {t[0]: t[1]}, zip(t1, t2))))l lambda t1, t2: [{i: j} for i, j in zip(t1, t2)]print(l(t1, t2))map内置函数使用&#xf…

UVALive 5903 Piece it together(二分图匹配)

给你一个n*m的矩阵&#xff0c;每个点为B或W或.。然后你有一种碎片。碎片可以旋转&#xff0c;问可否用这种碎片精确覆盖矩阵。N,M<500 WB 《碎片 W 题目一看&#xff0c;感觉是精确覆盖&#xff08;最近被覆盖洗脑了&#xff09;&#xff0c;但是仔细分析可以知道&#xf…

将undefault和null的数据转换成bool类型的数据 使用!!

<script> var o{}; var anull; console.info(!!o.name); </script> 输出false 此方法是将undefault和null的数据转换成bool类型的数据. var model avalon.define({ $id: model, defaultvalue {},});<span ms-if"!!defaultvalue .cost" >测试</…

springcloud(五):熔断监控Hystrix Dashboard和Turbine

Hystrix-dashboard是一款针对Hystrix进行实时监控的工具&#xff0c;通过Hystrix Dashboard我们可以在直观地看到各Hystrix Command的请求响应时间, 请求成功率等数据。但是只使用Hystrix Dashboard的话, 你只能看到单个应用内的服务信息, 这明显不够. 我们需要一个工具能让我们…

如何修改PKG_CONFIG_PATH环境变量

两种情况&#xff0c;如果你只是想加上某库的pkg&#xff0c;则选择下面其一&#xff1a;export PKG_CONFIG_PATH/usr/lib/pkgconfig/ 或者 export PKG_CONFIG_LIBDIR/usr/lib/pkgconfig/ 如果你想覆盖掉原来的pkg,选择后者。因为&#xff1a;PKG_CONFIG_LIBDIR的优先级比 PKG_…

python跨包导入包_python引入跨模块包

人生苦短&#xff0c;我学python。最近学习python&#xff0c;由于包的模块分的比较多。所以要用到跨模块引入 且调用中间的方法整体目录结构如下。需求&#xff1a;在 API模块 user.py 中 调用 plugin 模块中 douyin_login 下的方法。贴一下最终解决方案&#xff1a;from plug…

jdk1.8版本已经不包含jdbc.odbc连接

连接access的时候发现报错&#xff0c;无法加载jdbc.odbc类文件&#xff0c;到Java安装目录上jre/lib/rt.jar上找jdbcodbc类也没有了。 找个jdk1.7安装就ok啦。转载于:https://www.cnblogs.com/dohn/p/3707254.html

位运算问题

位运算 位运算是把数字用二进制表示之后&#xff0c;对每一位上0或者1的运算。 理解位运算的第一步是理解二进制。二进制是指数字的每一位都是0或者1.比如十进制的2转化为二进制之后就是10。在程序员的圈子里有一个流传了很久的笑话&#xff0c;说世界上有10种人&#xff0c;一…

conda环境管理介绍

我们可以使用conda 来切换不同的环境&#xff0c;主要的用法如下&#xff1a; 1. 创建环境 # 指定python版本为2.7&#xff0c;注意至少需要指定python版本或者要安装的包 # 后一种情况下&#xff0c;自动安装最新python版本conda create -n env_name python2.7# 同时安装必…

unable to execute dex: multiple dex files Cocos2dxAccelerometer

原文转载&#xff1a;http://discuss.cocos2d-x.org/t/conversion-to-dalvik-format-failed-unable-to-execute-dex-multiple-dex-files-define-lorg-cocos2dx-lib-cocos2dxaccelerometer/6652/4 用cocos2dx2.2.3没问题&#xff0c;用了3.1.1出现这个问题。确实够蛋疼。还要有这…

PHP javascript 值互相引用(不用刷新页面)

PHP javascript 值互相引用的问题 昨天通过EMAIL给一些公司投了简历&#xff0c;希望他们能给我一份工作&#xff0c;今天其中一家公司的人给我打电话&#xff0c;大意是要我做一点东西&#xff08;与AJAX有关&#xff09; 给他们看&#xff0c;我听打电话的人问我的问题&#…

mysql自增_面试官:为什么 MySQL 的自增主键不单调也不连续?

为什么这么设计(Why’s THE Design)是一系列关于计算机领域中程序设计决策的文章&#xff0c;我们在这个系列的每一篇文章中都会提出一个具体的问题并从不同的角度讨论这种设计的优缺点、对具体实现造成的影响。如果你有想要了解的问题&#xff0c;可以在文章下面留言。当我们在…

caffe 初学参考链接

最近在学习caffe&#xff0c;也搜集了一些资料&#xff0c;主要是一些网上公开的博客资源&#xff0c;现汇总一下&#xff0c;以便后面参考。 caffe 安装 编译py-faster-rcnn全过程caffe依赖库安装&#xff08;非root&#xff09;编译py-faster-rcnn的问题汇总及解决方法 ca…

java timer 定时任务

监听类1 package com.xx.model;2 3 import java.util.Calendar;4 import java.util.Date;5 import java.util.Timer;6 import javax.servlet.ServletContextEvent;7 import javax.servlet.ServletContextListener;8 import org.apache.commons.logging.Log;9 import org.apache…

python 打开txt_在python中从txt文件打开链接

我想请求一个rss程序的帮助。我所做的是收集包含我项目相关信息的网站&#xff0c;然后检查它们是否有rss提要。链接存储在txt文件中(每行一个链接)。因此&#xff0c;我有一个txt文件&#xff0c;其中包含了需要检查rss的基本url。在我找到了这个代码&#xff0c;这会使我的工…

IOS-awakeFromNib和viewDidLoad

awakeFromNib 当.nib文件被加载的时候&#xff0c;会发送一个awakeFromNib的消息到.nib文件中的每个对象&#xff0c;每个对象都可以定义自己的 awakeFromNib函数来响应这个消息&#xff0c;执行一些必要的操作。也就是说通过nib文件创建view对象是执行awakeFromNib 。 viewDid…