Pythonでスタックマシン風の計算機
タイトルそのまま。
import math global stack stack = [] numbers = map(str, range(0,10)) operators = ["+", "-", "/", "*"] def clear_stack(): for i in range(len(stack)): stack.pop() def concat(st): out = "" for i in range(0, len(st)): tmp = st.pop() if tmp in numbers or isinstance(tmp, float) or tmp == "." : out = str(tmp) + out else: stack.append(tmp) return float(out) return float(out) def calc(): r = stack.pop() op = stack.pop() l = stack.pop() if op == "+": return l + r if op == "-": return l - r if op == "/": return l / r if op == "*": return l * r def solve(token): if token == ".": if stack[len(stack)-1] != "." or len(stack) != 0: stack.append(".") if token in numbers: print "NUM:" + str(token) stack.append(token) if token in operators: if stack[len(stack)-1] in operators: stack.pop() stack.append(token) return print "OP:" + str(token) stack.append(concat(stack)) if len(stack) == 3: stack.append(calc()) stack.append(token) if token == "=": stack.append(concat(stack)) if len(stack) == 3: stack.append(calc()) if token == "%" and not stack[len(stack)-1] in operators: stack.append(concat(stack)) per = stack.pop() stack.append(stack[0] * (per/100)) if token == "r": stack.append(concat(stack)) tmp = stack.pop() stack.append(math.sqrt(tmp)) if token == "b": stack.pop() if token == "i": stack.append(concat(stack)) tmp = stack.pop() stack.append(1/tmp) if token == "c": stack.append(concat(stack)) if not stack[len(stack)-1] in operators: stack.pop() if token == "C": clear_stack() return if __name__ == "__main__": while 1: token = raw_input("> ") solve(token) print stack
bで一文字削除、rで平方根、iで逆数、cはCE、CはC、ほかはだいたい電卓と同じ。
まだ入力ステートの制御ができていないがそこそこ動く。
ざっくり書いたので非効率なところは多そう。
動作
$ python stack_calc.py > 1 NUM:1 ['1'] > 2 NUM:2 ['1', '2'] > = [12.0] > 1 NUM:1 [12.0, '1'] > + OP:+ [12.01, '+'] > / [12.01, '/'] > 10 [12.01, '/'] > 1 NUM:1 [12.01, '/', '1'] > 0 NUM:0 [12.01, '/', '1', '0'] > = [1.201] > r [1.0959014554237987] > + OP:+ [1.09590145542, '+'] > 8 NUM:8 [1.09590145542, '+', '8'] > 4 NUM:4 [1.09590145542, '+', '8', '4'] > % [1.09590145542, '+', 0.9205572225527999] > = [2.016458677973] > + OP:+ [2.01645867797, '+'] > 1 NUM:1 [2.01645867797, '+', '1'] > . [2.01645867797, '+', '1', '.'] > 1 NUM:1 [2.01645867797, '+', '1', '.', '1'] > = [3.11645867797]