rpn.py

Created by garycmartin

Created on August 22, 2018

2.16 KB

A simple RPN calculator (V0.3). Supports pi, e, rnd, !, *, +, -, /, acos, asin, atan, cos, deg, log, log10, pow, rad, recip, sin, sqr, sqrt and tan. Type ? for a list of operators, clr to clear the stack, swap to swap the two most recent stack items, roll to roll the stack, drop to drop the last stack item, and q to quit.

Example:

> 3 sqr 4 sqr + 5 sqr - 2 3 * 4 * / acos deg
[90.0]
> 4 sqr 5 sqr + 3 sqr - 2 4 * 5 * / acos deg
[90.0, 36.86989764584401]
> 5 sqr 3 sqr + 4 sqr - 2 5 * 3 * / acos deg
[90.0, 36.86989764584401, 53.13010235415599]
> +
[90.0, 90.0]
> +
[180.0]


# Simple RPN calculator

from math import *
from random import random

ops = {'+': [2, lambda x, y : x + y],
 '-': [2, lambda x, y : x - y],
 '*': [2, lambda x, y : x * y],
 '/': [2, lambda x, y : x / y],
 'sqr': [1, lambda x : x * x],
 'recip': [1, lambda x : 1 / x],
 'pow': [2, lambda x, y : pow(x, y)],
 '!': [1, lambda x : fact(int(round(x)))],
 'deg': [1, lambda x : degrees(x)],
 'rad': [1, lambda x : radians(x)],
 'log': [1, lambda x : log(x)],
 'log10': [1, lambda x : log10(x)],
 'sqrt': [1, lambda x : sqrt(x)],
 'sin': [1, lambda x : sin(x)],
 'cos': [1, lambda x : cos(x)],
 'tan': [1, lambda x : tan(x)],
 'asin': [1, lambda x : asin(x)],
 'acos': [1, lambda x : acos(x)],
 'atan': [1, lambda x : atan(x)]}

def evaluate(tokens, stack):
 for t in tokens:
  if t == 'pi':
   stack.append(pi)
  elif t == 'e':
   stack.append(e)
  elif t == 'rnd':
   stack.append(random())
  elif t == 'swap':
   try: a = stack.pop()
   except: return []
   try: b = stack.pop()
   except: return [a]
   stack.append(a)
   stack.append(b)
  elif t == 'roll':
   try: stack.insert(0, stack.pop())
   except: return []
  elif t == 'drop':
   try: stack.pop()
   except: return []
  elif t in ops:
   op = ops[t][1]
   if ops[t][0] == 1 and len(stack) >= 1:
    a = stack.pop()
    try: stack.append(op(a))
    except: print("Error"); stack.append(a)
   elif ops[t][0] == 2 and len(stack) >= 2:
    a = stack.pop()
    b = stack.pop()
    try: stack.append(op(b,a))
    except: print("Error"); stack.append(b); stack.append(a)
  elif set(t).issubset(set("0123456789.-")):
   stack.append(float(t))
  else:
   print("Unknown token %s" % t)
 return stack

def fact(n):
 f = 1
 while n > 0:
  f *= n; n -= 1
 return f

stack = []
while True:
  expression = input('> ')
  if expression is 'q':
   break
  elif expression is 'clr':
   stack = []
  elif expression is '?':
   print('Help:', end=' ')
   w = 0
   for o in sorted(list(ops.keys()) + ['rnd', '?', 'q', 'clr', 'pi', 'e', 'swap', 'roll', 'drop']):
    print(o, end=' ')
    w += 1
    if w > 5: print(); w = 0
   if w != 0: print()
   continue
  elif len(expression) == 0:
    continue
  else:
   stack = evaluate(expression.split(), stack)
  print(stack)