プログラミングの勉強をしながら式入力型の電卓を作りたいと思い調べたところ「逆ポーランド法」を知りました。
まず四則演算出来るものを作り最終的には関数電卓を目指そうと思っているのですが、この「逆ポーランド法」を取り入れた計算プログラムを学べば良いのでしょうか?もっと適している他の手法はありますか?
公開されている式入力型の電卓ソフトはどのような手法でプログラムされているのでしょうか?(なかなか式入力型のサンプルが見つからなくて…。)
言語はActiveBasicを使用していますが、情報が少ない為VisualBasicのサイトで勉強しています。
宜しくお願いいたします。
No.2ベストアンサー
- 回答日時:
逆ポーランド記法は、式の解析が簡単なので、作りやすいかもしれませんね。
逆ポーランド記法を解するする処理ルーチンを作って、一般入力式を逆ポーランド記法に変換するルーチンを作って渡しても良いと思いますが、四則演算くらいなら、構文解析やりつつ計算するのもそれほどは難しくはないです。
サンプルとしてVBで四則演算を理解して計算する関数を書いてみました
参考にしてみて下さい。
'"(3+5)*7-2"の様な文字列で与えられた式を計算する
Public Function calc(ByVal str As String) As Double
Const STACKSIZE = 3
Dim cstack(STACKSIZE) As String, csp As Integer '演算子スタック
Dim vstack(STACKSIZE) As Double, vsp As Integer '値スタック
Dim level As Integer
Dim sign As Integer, frac As Double
Dim wk As Double, cwk As String, c
Dim buff As String
Dim pos As Integer
str = Replace(str, " ", "") '式からスペースを取り除く
vsp = STACKSIZE
csp = STACKSIZE
csp = csp - 1 'スタックは使う前に-1する
cstack(csp) = "@" 'empty mark
wk = 0: sign = 0: frac = 10
For pos = 1 To Len(str) '一文字ずつ走査する
c = Mid(str, pos, 1) '現在着目している文字
If "0" <= c And c <= "9" Then '数字
If sign = 0 Then sign = 1
If frac = 10 Then
wk = wk * frac + Val(c)
Else
wk = wk + Val(c) * frac
frac = frac / 10
End If
Else
If c = "." Then '小数点
If frac < 1 Then
MsgBox "小数点が2つ以上ある"
calc = 0
Exit Function
Else
frac = 1 / 10
End If
Else '数ではない
If sign <> 0 Then '初めの時は積まない、例えば-で始まる数の時
vsp = vsp - 1
vstack(vsp) = sign * wk
End If
wk = 0: sign = 0: frac = 10 '数の初期化
If c = "-" Then '符号のマイナスの処理
If pos = 1 Then '最初にマイナス符号があれば符号
sign = -1
GoTo nextLoop
Else
If InStr("(*/-+)", Mid(str, pos - 1, 1)) > 0 Then 'マイナス符号の前が演算子の時符号
sign = -1
GoTo nextLoop
End If
End If
End If
Select Case c
Case "*", "/"
cwk = cstack(csp) '直前の演算子を取り出す
If cwk = "@" Or cwk = "+" Or cwk = "-" Then '現在の演算子が優先である
csp = csp - 1
cstack(csp) = c
Else
If cwk = "*" Then '掛け算する
vstack(vsp + 1) = vstack(vsp + 1) * vstack(vsp)
Else
If cwk = "/" Then '割り算する
vstack(vsp + 1) = vstack(vsp + 1) / vstack(vsp)
End If
End If
vsp = vsp + 1
cstack(csp) = c
End If
Case "-", "+"
cwk = cstack(csp)
If cwk = "@" Then
csp = csp - 1
cstack(csp) = c
Else
Select Case cwk
Case "+"
vstack(vsp + 1) = vstack(vsp + 1) + vstack(vsp)
Case "-"
vstack(vsp + 1) = vstack(vsp + 1) - vstack(vsp)
Case "*"
vstack(vsp + 1) = vstack(vsp + 1) * vstack(vsp)
Case "/"
vstack(vsp + 1) = vstack(vsp + 1) / vstack(vsp)
End Select
vsp = vsp + 1
cstack(csp) = c
End If
Case "(" 'カッコ中身でcalcを呼び出す
pos = pos + 1
level = 1 'カッコの組の数
sign = 1
buff = ""
Do While pos <= Len(str)
c = Mid(str, pos, 1)
If c = ")" Then
level = level - 1
If level = 0 Then
wk = calc(buff)
Exit Do
End If
Else
If c = "(" Then level = level + 1
End If
buff = buff & c
pos = pos + 1
Loop
If level > 0 Then 'カッコの数が合っていない時
wk = calc(buff)
pos = pos - 1
End If
Case ")" 'ありえないはず
MsgBox ("閉じカッコが多すぎる")
Case Else
MsgBox (c & "は使用できない文字です")
End Select
End If
End If
nextLoop:
Next
vsp = vsp - 1
vstack(vsp) = sign * wk
cwk = cstack(csp)
Do Until "@" = cwk
Select Case cwk
Case "+"
vstack(vsp + 1) = vstack(vsp + 1) + vstack(vsp)
Case "-"
vstack(vsp + 1) = vstack(vsp + 1) - vstack(vsp)
Case "*"
vstack(vsp + 1) = vstack(vsp + 1) * vstack(vsp)
Case "/"
vstack(vsp + 1) = vstack(vsp + 1) / vstack(vsp)
End Select
vsp = vsp + 1
csp = csp + 1
cwk = cstack(csp)
Loop
calc = vstack(vsp)
End Function
No.4
- 回答日時:
If InStr("(*/-+)", Mid(str, pos - 1, 1)) > 0 Then
の部分を
If InStr("*/-+", Mid(str, pos - 1, 1)) > 0 Then
に修正して下さい。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- その他(自然科学) 科学技術計算の仕事について 2 2023/02/04 18:09
- その他(プログラミング・Web制作) プログラムの勉強のおすすめは 7 2022/12/09 20:09
- 時計・電卓・電子辞書 電卓 5 2023/08/16 05:38
- Excel(エクセル) エクセル/列追加時、合計行の計算式 7 2023/03/15 11:14
- 時計・電卓・電子辞書 電卓 4 2022/04/29 06:26
- 夫婦 1、ジャージの裾あげについて質問です。 私は、ジャージやズボンを買うとき、お店に裾あげをお願いしてい 1 2023/02/06 15:34
- インターネット広告・アフィリエイト アフェリエイトサイト 作成について 5 2022/05/13 21:31
- 統計学 統計検定2級を取ろうと勉強中なのですが分からないことがあったので質問させていただきます。 スタージェ 6 2023/01/01 23:02
- 中学校 中2女子です。私は最近医者を目指したいと考えているのですが、目指す上でいくつか知りたいことがあります 10 2023/05/09 03:43
- 画像編集・動画編集・音楽編集 【急】【Zbrush】3DCG初心者です。ノートPCでのZbrush動作環境につきまして 1 2023/08/19 17:38
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
数値計算の高速化 (cos, sin, exp)
-
Perlでのルートの計算
-
Vb6.0で三角関数が使えない
-
VBAの再計算が反映されない件に...
-
Visual C++でdebugとreleaseで...
-
[急募]Pythonについてです。
-
R言語での極小値の指数形式での...
-
スライムがつぶれていく様子を...
-
60進数の四則計算
-
VB6.0でのバイナリデータの扱い...
-
傾いた四角形内の範囲の条件式
-
EXCELなどで「返す」という表現
-
VB6で正確なミリ秒を計測したい...
-
CとFORTRANの計算速度はどちら...
-
Excel VBAの残業時間の合計計算...
-
VBでReplace
-
10進数から8進数へ
-
順列のプログラムについて(VB)
-
Javascrptの0の掛け算
-
エクセルで特定のセルのみを任...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
65536は2の何乗なのでしょうか?
-
VBAの再計算が反映されない件に...
-
排他的論理和 BCC(水平パリテ...
-
EXCELなどで「返す」という表現
-
C言語の課題で、1年の秒数を計...
-
バッチファイルでウインドウを...
-
骨折リスク評価のFRAXについて...
-
変化させるセルが変化しない
-
CとFORTRANの計算速度はどちら...
-
なぜオーバーフローになるので...
-
数値計算の高速化 (cos, sin, exp)
-
モジュラス103の計算とは何でし...
-
C# 計算処理中に実行中ウィン...
-
モジュロ
-
引き放し法による除算アルゴリ...
-
60進数の四則計算
-
C言語についてです。 再帰を使...
-
Perlで時間の計算
-
CRC8を教えてください
-
傾いた四角形内の範囲の条件式
おすすめ情報