リストを配列で定義し、スタックはそのリストを利用するように定義、正規表現をコード化、内部クラスの殆どを展開しました。
簡単になったとは思えませんが…。
係数優先モード指定追加。 6/2(1+2)
の結果を選べます。(true なら 1、 false なら 9)
java
1class List {
2 private String[] values = new String[0];
3 private int size = 0;
4 List() {}
5 List(List org) {
6 size = org.size;
7 values = new String[org.values.length];
8 for(int i=0; i<size; i++) values[i] = org.values[i];
9 }
10 11
12 void add(String v) {
13 if(size == values.length) {
14 String[] newValues = new String[values.length + 10];
15 for(int i=0; i<size; i++) newValues[i] = values[i];
16 values = newValues;
17 }
18 values[size++] = v;
19 }
20 2122
23 String remove(int i) {
24 String v = values[i];
25 for(size--; i<size; i++) values[i] = values[i+1];
26 return v;
27 }
28 2930
31 String get(int i) { return values[i]; }
32 3334
35 void set(int i, String v) { values[i] = v; }
36 37
38 int size() { return size; }
39 @Override
40 public String toString() {
41 String s = "[";
42 for(int i=0; i<size; i++) s += (i>0?", ":"") + values[i];
43 s += "]";
44 return s;
45 }
46}
47
48class Stack {
49 private List list = new List();
50 51
52 void push(String v) { list.add(v); }
53 54
55 String pop() { return list.remove(list.size()-1); }
56 57
58 String peek() { return list.get(list.size()-1); }
59 60
61 boolean isEmpty() { return list.size() == 0; }
62}
63
64public class Main {
65 public static void main(String[] args) {
66 String[] testdata = { "1+2.5*-3", "100*50/20", "(20+30)*5", "2(3+5)/4", "1+(2(3+((5/2)-2)))", "6/2(1+2)" };
67 for(String formula : testdata) {
68 RPN rpn = new RPN(formula, true);
69 System.out.println(rpn + "=" + rpn.calc());
70 }
71 }
72
73 private static class RPN {
74 private static class Translator {
75 private final String formula;
76 private int index;
77 private Stack stack = new Stack();
78 private List list = new List();
79
80 Translator(String formula) {
81 this.formula = formula;
82 }
83
84 List translate(boolean coefficientPriorityMode) {
85 int mode = 0;
86 while(!isEnd()) {
87 if(mode == 0) {
88 if(getChar() == '(') {
89 putOp(nextOperator());
90 } else {
91 putValue(nextNumber());
92 mode = 1;
93 }
94 } else {
95 String op = nextOperator();
96 if(op.equals(")")) {
97 putOp(op);
98 } else {
99 if(op.equals("(")) putOp(coefficientPriorityMode ? "**" : "*");
100 putOp(op);
101 mode = 0;
102 }
103 }
104 }
105 return complete();
106 }
107
108 private boolean isEnd() { return index >= formula.length(); }
109 private char getChar() { return formula.charAt(index); }
110 private String nextOperator() {
111 String op = "" + formula.charAt(index++);
112 if("+-*/()".indexOf(op.charAt(0)) < 0) throw new IllegalArgumentException("Operator Error: index=" + index);
113 return op;
114 }
115 private String nextNumber() {
116 int j, i = index + (formula.charAt(index)=='-'?1:0);
117 for(j=0; i<formula.length() && ('0'<=formula.charAt(i) && formula.charAt(i)<='9'); i++, j++);
118 if(j > 0 && i < formula.length() && formula.charAt(i) == '.') {
119 for(i++, j=0; i<formula.length() && ('0'<=formula.charAt(i) && formula.charAt(i)<='9'); i++, j++);
120 }
121 if(j == 0) throw new IllegalArgumentException("Number Error: index=" + index);
122 String v = formula.substring(index, i);
123 index = i;
124 return v;
125 }
126
127 private void putOp(String op) {
128 if(op.equals(")")) {
129 while(!stack.isEmpty() && !(op=stack.pop()).equals("(")) list.add(op.toString());
130 if(!op.equals("(")) throw new IllegalStateException("Formula Error: Unmatched parentheses.");
131 return;
132 }
133 if(!op.equals("(")) {
134 while(!stack.isEmpty() && getPri(stack.peek()) >= getPri(op)) list.add(stack.pop());
135 }
136 stack.push(op);
137 }
138 private int getPri(String op) {
139 if(op.equals("**")) return 3;
140 if(op.equals("*") || op.equals("/")) return 2;
141 if(op.equals("+") || op.equals("-")) return 1;
142 return 0;
143 }
144 private void putValue(String v) {
145 list.add(v);
146 }
147 private List complete() {
148 while(!stack.isEmpty()) list.add(stack.pop());
149 for(int i=0; i<list.size(); i++) if(list.get(i).equals("**")) list.set(i, "*");
150 return new List(list);
151 }
152 }
153
154 private final String formula;
155 private List list;
156
157 RPN(String formula, boolean coefficientPriorityMode) {
158 this.formula = formula;
159 list = new Translator(formula).translate(coefficientPriorityMode);
160 }
161
162 String calc() {
163 Stack stack = new Stack();
164 for(int i=0; i<list.size(); i++) {
165 String s = list.get(i);
166 if(s.equals("+")) {
167 double b = Double.parseDouble(stack.pop());
168 double a = Double.parseDouble(stack.pop());
169 stack.push("" + (a + b));
170 } else if(s.equals("-")) {
171 double b = Double.parseDouble(stack.pop());
172 double a = Double.parseDouble(stack.pop());
173 stack.push("" + (a - b));
174 } else if(s.equals("*")) {
175 double b = Double.parseDouble(stack.pop());
176 double a = Double.parseDouble(stack.pop());
177 stack.push("" + (a * b));
178 } else if(s.equals("/")) {
179 double b = Double.parseDouble(stack.pop());
180 double a = Double.parseDouble(stack.pop());
181 stack.push("" + (a / b));
182 } else {
183 stack.push(s);
184 }
185 }
186 return stack.pop();
187 }
188
189 @Override
190 public String toString() {
191 return formula + "=" + list;
192 }
193 }
194}
1+2.5*-3=[1, 2.5, -3, *, +]=-6.5
100*50/20=[100, 50, *, 20, /]=250.0
(20+30)*5=[20, 30, +, 5, *]=250.0
2(3+5)/4=[2, 3, 5, +, *, 4, /]=4.0
1+(2(3+((5/2)-2)))=[1, 2, 3, 5, 2, /, 2, -, +, *, +]=8.0
6/2(1+2)=[6, 2, 1, 2, +, *, /]=1.0