逆ポーランド記法電卓を作ろう! - 金沢市・野々市市・白山市の塾なら東大セミナー
2026.01.30プログラミングの目で高校数学を見ると

逆ポーランド記法電卓を作ろう!


 

皆さんこんにちは、東進衛星予備校 金沢南校の北川です。

勉強のおともに、或いは経理作業の要に、電卓が必要になることって多いですよね。私も入試問題の解説を作るために、幾度となく電卓を使ってきました。

そんな電卓ですが、やっていることと言えばパソコン内部で簡単な計算をするだけです。実際、プログラミングを勉強すると最初に電卓を作るというケースも多いと聞きます[1]

今回は「逆ポーランド記法」という計算式の書き方を使って、加減乗除ができる電卓を作ってみることにします。

Pythonのごく初歩の記法のみ知っていれば理解できる内容ですので、是非お楽しみください。

目次
1.電卓を作るのって本当に簡単か? ~逆ポーランド記法はここが強い~
2.雑に作ると鼻から悪魔が飛び出してくる ~Devide by Zero~
3.おわりに

1.電卓を作るのって本当に簡単か? ~逆ポーランド記法はここが強い~

実際に電卓を作ろうと思ったときに、どういう風に作るのが最も楽でしょうか。

人間の直観に合わせて考えてみると、例えば3+5-2を計算しようと思ったら、次のように計算するはずです。

1.3と5を足して8にする。8を覚えておく。

2.覚えておいた8から2を引いて、5になる。

3.答えは5だ!

これは、先頭から与えられた順に処理をするということに他なりません。この、「頭から処理する」というのを実装するなら、途中の計算結果を覚えておく場所さえあれば良いことになります。

しかし、これですべて上手く行くわけではありません。

例えば3+5×2のような式はどうでしょう。掛け算を先に処理しますから、頭から順に計算するわけにはいかなくなってしまいます。

しかしこの場合も、ちょっとした工夫と覚える量を増やすことで、さっきのアイデアを使えるようになります。

ズバリ、演算子(+,-,×,÷)を与える順番を工夫すればよいのです。

1.3と言われるので、3を覚えておく。

2.5と言われるので、5を次に覚えておく。

3.2と言われるので、2を次に覚えておく。

4.×と言われるので、覚えているうち新しいほうから2つである2と5を取り出して、掛ける。取り出した分を忘れて、10を新しく覚えておく。

5.+と言われるので、覚えているうち新しいほうから2つである10と3を取り出して、足す。取り出した分を忘れて、13を新しく覚えておく。

6.13が答えだ!

このようにすれば、「頭から処理する」を「頭から数字が来た順に処理する」という形に少し変えるだけで上手く行きます。あとから計算するものだけ覚えておいて、そのように処理をするのです。

これは、「3+5×2」という式を、「3 5 2 × +」という形で書いて、前から見える順に処理をしたものだと考えることができます。このように、数字だけを先に書き、後に使う演算子ほど後ろに配置する記法のことを逆ポーランド記法と言います。

この記法は人間にとっては分かりにくいですが、逐次処理を基本とするコンピュータにとっては何かと都合の良いことが多いのです。なぜなら、「数字も演算子も前から来た順に処理すればいい」からです。

要するに「数字が来れば覚えておく」、「演算子が来たら覚えてある数から2つ取り出して計算し、新しく1つ覚える」というたった2つの簡単なルールで電卓が作れてしまうのです!

今の話は、素朴には以下のように実装できます。変数stackに数字を格納し、演算子が来たらstackから変数を取り出して計算するという形です。


def calcurate(a, b, s):
    if s == '+':
        return b + a
    elif s == '-':
        return b - a
    elif s == '*':
        return b * a
    elif s == '/':
        return b / a

strings = list(input().split())

stack = []

for i in range(len(strings)):
    match strings[i]:
        case('+' | '-' | '*' | '/'):
            a = stack.pop()
            b = stack.pop()
            stack.append(calcurate(a, b, strings[i]))
        case _:
            stack.append(int(strings[i]))

print('計算結果は', stack[0], 'です')

入力は逆ポーランド記法で、各数字や演算子の間にスペースを入れます。


3 5 2 * +

出力は以下の通り。


13

2.雑に作ると鼻から悪魔が飛び出してくる ~エラー処理~

さて、ではこれでめでたしめでたしかというと、そんなことはありません。

例えば、以下のような入力があった場合はどうなるでしょう?


3 0 /

これは3を0で割れと言っていますから、当然エラーを吐いて停止してしまいます。

他にも、こちとら人間なので、奇怪な入力を行ってしまう可能性があります。


3 + 5

上記の入力は人間だと普通ですが、パソコンは困ってしまいます。

なぜなら、今のルールは「演算子が来たら覚えている数字を2つ取り出す」ですので、これだと数字が「3」しかない状態で無理やり2つ取り出してしまうことになるからです。これもエラーになってしまいます。

あるいは、人間はポンコツなので、スペースを入れずに入力してしまうかもしれません。


3+5

今のままだと、「スペースがあったら文字を分ける」という形で入力を受け取っているため、「3+5」でひとかたまりとしてパソコンが認識してしまいます。詳しい説明は避けますが、このままだとエラーになってしまいます。

そこで、分岐を書いてエラー処理を行うことにします。さっきのエラーはそれぞれざっくり、「0で割るエラー」「存在しないリスト番号にアクセスしてしまうエラー」「変換できない文字が来ちゃうエラー」になりますから、これが来た時に回避するようなプログラムにすればよいです。

Pythonではtry~except文と呼ばれている内容を使って書き直すと、こうなります。


def calcurate(a, b, s):
    if s == '+':
        return b + a
    elif s == '-':
        return b - a
    elif s == '*':
        return b * a
    elif s == '/':
        return b / a

strings = list(input().split())

stack = []

for i in range(len(strings)):
    match strings[i]:
        case('+' | '-' | '*' | '/'):
            try:
                a = stack.pop()
                b = stack.pop()
                stack.append(calcurate(a, b, strings[i]))
            except IndexError:
                print('演算子に対して数字が少ないようです')
                break
            except ValueError:
                print('不正な入力です')
                break
            except ZeroDivisionError:
                print('0で割ることはできません')
                break
        case _:
            stack.append(int(strings[i]))

print('計算結果は', stack[0], 'です')

これに、浮動小数点数を扱うことによる誤差を避けるためにfractionsライブラリを使って分数を実装したものが以下になります。これで電卓は完成です!


import fractions

def calcurate(a, b, s):
    if s == '+':
        return b + a
    elif s == '-':
        return b - a
    elif s == '*':
        return b * a
    elif s == '/':
        return fractions.Fraction(b, a)

strings = list(input().split())

stack = []

for i in range(len(strings)):
    match strings[i]:
        case('+' | '-' | '*' | '/'):
            try:
                a = stack.pop()
                b = stack.pop()
                stack.append(calcurate(a, b, strings[i]))
            except IndexError:
                print('演算子に対して数字が少ないようです')
                break
            except ValueError:
                print('不正な入力です')
                break
            except ZeroDivisionError:
                print('0で割ることはできません')
                break
        case _:
            stack.append(int(strings[i]))

print('計算結果は', stack[0], 'です')

3.おわりに

こうして、四則演算だけなら正確に計算できる逆ポーランド記法電卓が完成しました。

この記法は、数字と計算順と計算内容だけを順に並べればいいので非常に簡潔であり、こういう場合に非常に役に立つものです。

基本情報技術者試験等の出題範囲にも逆ポーランド記法は含まれています。当時は「なんでこんな意味不明な記法を使うねん」と思っていましたが、こうした時に頭から処理するのにこれほどおあつらえむきな記法もないんだなと理解できました。

逆ポーランド記法ですが、実は共通テスト情報Iの前身ともいえる「情報関係基礎」という科目で類似の概念が問われたこともあります(計算ではなく、トーナメント戦の表記方法についてでしたが)。今後の情報Iにも類似の出題があり得ますので、覚えておいて損はないでしょう。

今回の内容はここまで。次回もまたお会いしましょう!

  1.  私が電卓を作ってみたのはずいぶん最近のことになるので、人によると思いますが……。
    back
SNSでシェアする
カテゴリ
 

【記事監修者】塾長 柳生 好春


1951年5月16日生まれ。石川県羽咋郡旧志雄町(現宝達志水町)出身。中央大学法学部法律学科卒業。 1986年、地元石川県で進学塾「東大セミナー」を設立。以来、38年間学習塾の運営に携わる。現在金沢市、野々市市、白山市に「東大セミナー」「東進衛星予備校」「進研ゼミ個別指導教室」を展開。 学習塾の運営を通じて自ら課題を発見し、自ら学ぶ「自修自得」の精神を持つ人材育成を行い、社会に貢献することを理念とする。

ページTOPへ
Instagram X facebook