Javaで逆ポーランド記法変換・計算プログラムを作ってみた(計算編)
どうも、じゃがいもの方のポテト君です(?)
宣伝ですが(なぜここで?)少し前に僕のホームページを作ったのでぜひ見てってください~
前回は変換をしました。
ということで、今回は計算をやっていきます。
まあそもそもRPNはコンピューターが計算しやすくするための形式なので、計算自体は簡単です。
今回変数は使わず
10+(-1)
→[10][-1]+
のようにしてあるので、[ ]内の-にさえ注意すれば、基本的なアルゴリズムは準備編のまま記述するだけです。
準備編でも言ったように、
先頭から式を読み取り
値ならスタックに入れる
演算子ならスタックから2つの要素を取り出して演算をする(演算後の結果をスタックに戻す)
を行えば答えがでます。
ということで、作っていきます。
//前回作ったRPNクラス内に記述
static Double rpcal(String form){
char[] formc=form.toCharArray();
double ret,val,valf,vall;
String keep="";
Deque<String> sta=new ArrayDeque<>();
for(char c:formc){
switch(c){
case '[':
keep="[";
break;
case ']':
sta.addFirst(keep.substring(1));
keep="";
break;
case '+':
val=Double.valueOf(sta.removeFirst())+Double.valueOf(sta.removeFirst());
sta.addFirst(String.valueOf(val));
break;
case '-':
if(keep=="["){
keep+=String.valueOf(c);
break;
}
valf=Double.valueOf(sta.removeFirst());
vall=Double.valueOf(sta.removeFirst());
sta.addFirst(String.valueOf(vall-valf));
break;
case '*':
val=Double.valueOf(sta.removeFirst())*Double.valueOf(sta.removeFirst());
sta.addFirst(String.valueOf(val));
break;
case '/':
valf=Double.valueOf(sta.removeFirst());
vall=Double.valueOf(sta.removeFirst());
sta.addFirst(String.valueOf(vall/valf));
break;
default:
keep+=c;
break;
}
}
ret=Double.valueOf(sta.removeFirst());
return ret;
}
前回と同じく、式(既にRPNに変換した上で受け取ります)をchar型の配列に変換し(3.)、1文字ずつfor文(7~42)に渡してswitch文(8~41)で処理します。
switch文の中を説明していきます。[ ]は無視して数値だけ扱いたいところですが、[はkeep(5.)に保存しておき(21~24)、-が来た時keepに[があれば数値の一部として扱うようにしています(20~24)。文字が数値や . であるときは、デフォルトとしてkeepに追加します(38~40)。]が来た時がその数値の終わりと認識し、keep内の数値(最初の文字は[なので消す)をスタックにプッシュ(追加)します(12~15)。このときkeepの中身を消しておきます(14.)。演算子の時は、スタックから要素を2つポップ(取り出し)し、double型に変換して計算し、結果を文字列に戻してスタックにプッシュします(16~37)。準備編でも言いましたが、例えばab-はスタックにはbaの順で入っているので、a-bにするには
後にポップした要素-先にポップした要素
にしなければいけません(+と*は可換なので気にしなくていいです)。
これで、最後にスタックに残った要素が答えになります(43~44)。
ということで、RPN変換・計算ツールの完成です!
次はどんなプログラムを紹介しましょうかねー、次回もよろしくです!