Java 逆ポーランド記法とスタック操作による四則計算機 ソースコード ― 2022年08月12日 11:31
/** *********************************** */
/* 逆ポーランド記法とスタック操作による四則計算機 */
/** *********************************** */
import java.awt.*;
import java.util.Deque;
import java.util.ArrayDeque;
import java.util.HashMap;
import java.util.Map;
public class algopol extends java.applet.Applet {
TextField txtPorand, txtAns;
Button btnKeisan;
TextField txtMoto;
Button btnHenkan;
public void start() {
txtMoto = new TextField(20);
btnHenkan = new Button("変換");
txtPorand = new TextField(20);
txtAns = new TextField(20);
btnKeisan = new Button("計算");
txtMoto.setText("元の計算式");
txtPorand.setText("逆ポーランド式");
txtAns.setText("計算結果");
add(txtMoto);
add(btnHenkan);
add(txtPorand);
add(btnKeisan);
add(txtAns);
}
public boolean action(Event evt, Object what) {
if (evt.target == btnHenkan) {
txtPorand.setText(toRPN(txtMoto.getText()));
}
if (evt.target == btnKeisan) {
//r=res(stf.getText()); /* 書かれた式を計算 */
//rf.setText(String.valueOf(r)); /* 結果を表示 */
txtAns.setText(parseRPN(txtPorand.getText()));
return true;
}
return false;
}
public static void main(String[] args) {
// TODO code application logic here
new MyFrame("逆ポーランド式 四則計算機", new algopol(), 500, 500);
}
/** <h1>逆ポーランド記法(Reverse Polish Notation)[=後置記法:postfix notation]を計算する</h1>
* <p>
* スペースで区切った "10 20 30 * +" のような形式。連続した空白は1つ分の空白として処理される。
* <br>四則演算(+, -, *, /)と括弧のみ。</p>
*
* @param rpn : 逆ポーランド記法での計算式
* @return<b>int</b> : 計算された値
*/
public static final String parseRPN(final String rpn) {
final Deque<String> stack = new ArrayDeque<String>();
double aa, bb;
String s = rpn.replaceAll("\\s+", " "); //連続した空白文字をスペース1つ分に置き換える
final String[] arr = s.trim().split(" ");
for (String e : arr) {
if ('0' <= e.charAt(0) && e.charAt(0) <= '9') { //数字
stack.push(e);
} else {
aa = Double.parseDouble(stack.pop());
bb = Double.parseDouble(stack.pop());
if (e.equals("*")) {
stack.push(String.valueOf(bb * aa));
} else if (e.equals("/")) {
stack.push(String.valueOf(bb / aa)); // div/0 でInfinityとなる
} else if (e.equals("+")) {
stack.push(String.valueOf(bb + aa));
} else if (e.equals("-")) {
stack.push(String.valueOf(bb - aa));
}
}
}
return stack.pop();
}
/**
* 逆ポーランド記法用の演算子優先順位
*/
@SuppressWarnings("serial")
static final Map<Character, Integer> rpnRank = new HashMap<Character, Integer>() {
{//ブロックで記述
put('(', 4); //※数値が高いほど、優先順位が高いとする
put('#', 3); //オペランド(数値)[キーはダミー]
put('*', 2);
put('/', 2);
put('+', 1);
put('-', 1);
put(')', 0);
}
};
/** <h1>式を逆ポーランド記法(Reverse Polish Notation)[=後置記法:postfix notation]に変換する</h1>
* <p>
* スペースを含まない "10+20*30-40+50" のような式。空白文字は全て除去される。
* <br>四則演算(+, -, *, /)と括弧のみ。除算は整数除算(小数点以下切り捨て)。</p>
*
* @param expression : 変換する式
* @return<b>String</b> : 逆ポーランド記法に変換された式
*/
public static final String toRPN(final String expression) {
final Deque<Character> stack = new ArrayDeque<Character>();
String s = expression.replaceAll("\\s+", ""); //空白文字を取り除く
s = "(" + s + ")"; //末尾に")"を付けることで、最後にスタックを吐き出させる
final int len = s.length();
String ans = ""; //戻値用(RPN式)バッファ
String tmp = ""; //数字用バッファ
for (int i = 0; i < len; i++) {
char c = s.charAt(i);
if ('0' <= c && c <= '9') {
tmp += c; //数字1文字ずつのため
} else {
if (!tmp.equals("")) {
if (ans.length() > 0) {
ans += " ";
}
ans += tmp;
tmp = "";
}
while (!stack.isEmpty() && rpnRank.get(stack.peek()) >= rpnRank.get(c) && stack.peek() != '(') {
if (ans.length() > 0) {
ans += " ";
}
ans += stack.pop();
}
if (c == ')') {
stack.pop(); //'('
} else {
stack.push(c);
}
}
}
return ans;
}
}
コメント
トラックバック
このエントリのトラックバックURL: http://tukasa.asablo.jp/blog/2022/08/12/9517102/tb