# 现代软件工程课程作业 第一章第1题

  1 package cn.edu.tju.showmethecode.calculate;
2
3 import java.util.Stack;
4
5 import sun.rmi.runtime.Log;
6
7
8 public class RPNExpression {
9
10     private Stack<Object> RPNExp = new Stack<Object>();    //逆波兰表达式
11     private int length;            //运算数个数
12     private String value;        //表达式的值
13
14     public RPNExpression() {
15         this(4);
16     }
17
18     public RPNExpression(int length) {
19         if(length<2)
20             throw new IllegalArgumentException("长度设置过短！");
21
22         this.length = length;
23         generateRPNExp(length);
24         calcValue();
25     }
26
27     private void generateRPNExp(int length) {
28         int symbolCount = 0;
29         int operatorCount = 0;
30         while(operatorCount + symbolCount < length * 2 - 1){
31
32             if(operatorCount-1 > symbolCount && operatorCount < length){
33                 if(Utils.getRandomBoolean()){        //true生成运算符，false操作数
34                     this.RPNExp.push(generateSymbol());
35                     symbolCount ++;
36                 }else{
37                     this.RPNExp.push(Utils.getRandomBoolean() ? generateNumeric() : generateProperFraction());
38                     operatorCount ++;
39                 }
40             }else if(operatorCount-1 <= symbolCount && operatorCount < length) {                                    //true生成整数，false生成分数
41                 this.RPNExp.push(Utils.getRandomBoolean() ? generateNumeric() : generateProperFraction());
42                 operatorCount ++;
43             }else if(operatorCount-1 > symbolCount && operatorCount >=length) {
44                 this.RPNExp.push(generateSymbol());
45                 symbolCount ++;
46             }
47         }
48     }
49
50     private int generateNumeric() {
51         return Utils.getRandomInteger(1, 100);
52     }
53
54     private char generateSymbol() {
55         char[] symbol = {'+','−','×','÷'};
56         return symbol[Utils.getRandomInteger(0, 4)];
57     }
58
59     private ProperFraction generateProperFraction() {
60         int denominator = Utils.getRandomInteger(2, 10);
61         int numerator = Utils.getRandomInteger(1, denominator);
62         return new ProperFraction(numerator, denominator);
63     }
64     /*
65      * get逆波兰表达式
66      */
67     public static String generateArithmetic(int length){
68         return (new RPNExpression(length)).convertToSeqExp();
69     }
70
71     private void calcValue(){
72         Stack<Object> RPNStack = Utils.cloneStack(this.RPNExp);
73         Stack<Object> numStack = new Stack<Object>();            //数字栈
74
75         while(!RPNStack.empty()){
76             if(RPNStack.peek() instanceof Integer || RPNStack.peek() instanceof ProperFraction){
77                 numStack.push(RPNStack.pop());
78             }else if(RPNStack.peek() instanceof Character){
79                 Object rightOperator = numStack.pop();
80                 Object leftOperator = numStack.pop();
81                 if(rightOperator instanceof Integer)
82                     rightOperator = new ProperFraction((Integer) rightOperator, 1);
83                 if(leftOperator instanceof Integer)
84                     leftOperator = new ProperFraction((Integer) leftOperator, 1);
85
86                 switch ((Character) RPNStack.pop()) {
87                 case '+':
89                     break;
90                 case '−':
91                     numStack.push(((ProperFraction)leftOperator).minus((ProperFraction)rightOperator));
92                     break;
93                 case '×':
94                     numStack.push(((ProperFraction)leftOperator).multiply((ProperFraction)rightOperator));
95                     break;
96                 case '÷':
97                     numStack.push(((ProperFraction)leftOperator).devide((ProperFraction)rightOperator));
98                     break;
99                 default:
100 //                    throw new Exception("");
101                     break;
102                 }
103             }
104         }
105
106         this.value = ((ProperFraction) numStack.pop()).toString();
107     }
108
109     private String convertToSeqExp() {
110         System.out.println(this.RPNExp.toString());
111         Stack<Object> RPNStack = Utils.cloneStack(this.RPNExp);
112         Stack<String> tempExpStack = new Stack<String>();        //临时表达式栈
113
114         while(!RPNStack.empty()){
115             if(RPNStack.peek() instanceof Integer || RPNStack.peek() instanceof ProperFraction){
116                 tempExpStack.push(RPNStack.pop().toString());
117             }else if(RPNStack.peek() instanceof Character){
118                 String rightOperator = tempExpStack.pop();
119                 String leftOperator = tempExpStack.pop();
120
121                 if("×÷−".contains(RPNStack.peek().toString())){
122                     if(isNeedBrackets((Character) RPNStack.peek(), rightOperator, true)){
123                         rightOperator = "( " + rightOperator + " )";
124                     }
125                     if(isNeedBrackets((Character) RPNStack.peek(), leftOperator, false)){
126                         leftOperator = "( " + leftOperator + " )";
127                     }
128                 }
129
130                 tempExpStack.push(leftOperator + " " + RPNStack.pop().toString() + " " + rightOperator);
131             }
132         }
133
134         return tempExpStack.pop();
135     }
136
137     /*
138      * 判断一个临时表达式是否需要加括号，
139      * 有三种情况：
140      * 1. 当前符号是 ×÷，临时表达式符号是 +−
141      * 2. 当前符号是 −，临时表达式是右操作数，且符号为 +−
142      * 3. 当前符号是 ÷，临时表达式是右操作数，且符号为 ×÷
143      */
144     private boolean isNeedBrackets(Character currentSymbol, String tempExp, boolean rightOrNot) {
145         //判断括号外是什么符号
146         String priority = symbolOutsideOfBranckets(tempExp);
147
148         if("+−".equals(priority) && "×÷".contains(currentSymbol.toString())) {
149             return true;
150         }
151         if("×÷".equals(priority) && rightOrNot && "÷".equals(currentSymbol.toString())) {
152             return true;
153         }
154         if("+−".equals(priority) && rightOrNot && "−".equals(currentSymbol.toString())) {
155             return true;
156         }
157
158         return false;
159     }
160
161     /*
162      * 判断临时操作数最外层的符号是什么，×÷ 或 +− 后者无符号
163      * count是括号的左括号的数量
164      */
165     private String symbolOutsideOfBranckets(String tempExp) {
166         if(!tempExp.contains(" ")){
167             return "nothing";
168         }
169
170         String[] elements = tempExp.split(" ");
171         int count = 0;
172
173         for(int i=0; i<elements.length; i++){
174             if(count == 0 && "+−".contains(elements[i])) {
175                 return "+−";
176             }else if("(".equals(elements[i])) {
177                 count ++;
178             }else if(")".equals(elements[i])) {
179                 count --;
180             }
181         }
182         return "×÷";
183     }
184
185     public int getLength() {
186         return this.length;
187     }
188
189     public String getSeqExp() {
190         return convertToSeqExp();
191     }
192
193     public String getValue() {
194         return this.value;
195     }
196
197     public String toString() {
198         Stack<Object> RPNStack = Utils.cloneStack(this.RPNExp);
199         StringBuilder sb = new StringBuilder();
200         while(!RPNStack.empty())
201             sb.append(RPNStack.pop().toString()).append(" ");
202         return sb.toString();
203     }
204 }
RPNExpression

posted @ 2016-09-11 22:26  TalkIsCheap_5  阅读(213)  评论(0编辑  收藏  举报