用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.pswp.cn/news/258682.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/258682.shtml
英文地址,請注明出處:http://en.pswp.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…