rpn_dev.py

Created by garycmartin

Created on August 23, 2018

2.7 KB

More powerful version of the RPN code in development, treat as unstable expect to use most of your available program memory. Additions over the simple RPN version are; str and rcl for storing and recalling a memory value; auto for standard format numbers; fix for setting fixed decimal notation (push a number to the stack first for the number of places, i.e. 2 fix for rounding to two decimal places); eng for engineering notation (where the exponent is in powers of a thousand); si for displaying International System units (G, M, k, m, u, n, etc).


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],
 'pow': [2,lambda x,y: pow(x,y)],
 'sqr': [1,lambda x: x*x],
 'recip': [1,lambda x : 1/x],
 '!': [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)],
 'pi': [0,pi],
 'e': [0,e],
 'rnd': [0,random()]}

def evaluate(tokens, s, mem):
 for t in tokens:
  if t == 'swap':
   if len(s) >= 2:
    a = s.pop(); b = s.pop()
    s.append(a); s.append(b)
  elif t == 'roll':
   if len(s) >= 2: s.insert(0, s.pop())
  elif t == 'drop':
   if len(s) >= 1: s.pop()
  elif t == 'clr':
   s = []
  elif t == 'sto':
   if len(s) >= 1: mem = s[-1]
  elif t == 'rcl':
   s.append(mem)
  elif t in ops:
   op = ops[t][1]
   q = ops[t][0]
   if q == 0:
    s.append(op)
   elif q == 1 and len(s) >= 1:
    a = s.pop()
    try: s.append(op(a))
    except: print("Err"); s.append(a)
   elif q == 2 and len(s) >= 2:
    a = s.pop(); b = s.pop()
    try: s.append(op(b,a))
    except: print("Err"); s.append(b); s.append(a)
  elif set(t).issubset(set("0123456789.-")):
   s.append(float(t))
  else:
   print("Err %s" % t)
 return s, mem

def p(s):
 print(s, end='')

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

def eng_not(n, fix):
 for exp in range(-24, 25, 3):
  if abs(n) < pow(10, exp): break
 return '{}E{}'.format(n/float(pow(10, exp-3)), exp-3)

def si_not(n, fix):
 i = 0
 for exp in range(-24, 25, 3):
  if abs(n) < pow(10, exp): break
  i += 1
 u = 'yzafpnum kMGTPEZY'[i-1]
 if u == ' ': u = ''
 return '{}{}'.format(n/float(pow(10, exp-3)), u)

s = []
mem = 0.0
fix = 3
mode = 0
while True:
 expr = input('> ')
 if expr == 'q':
  break
 elif expr == 'fix':
  if len(s) >= 1: fix = abs(int(round(s.pop()))); auto = False
 elif expr == 'auto':
  mode=0
 elif expr == 'eng':
  mode=1
 elif expr == 'si':
  mode=2
 elif expr == '?':
  print('Help:', end=' ')
  w = 0
  for o in sorted(list(ops.keys()) + ['fix','eng','si','auto','sto','rcl','?','q','clr','swap','roll','drop']):
   print(o, end=' '); w += 1
   if w > 5: print(); w = 0
  if w != 0: print()
  continue
 elif len(expr) == 0:
   continue
 else:
   s, mem = evaluate(expr.split(), s, mem)
 print('[', end='')
 for i in s:
  if mode==0: p(i)
  elif mode==1: p(eng_not(i, fix))
  elif mode==2: p(si_not(i, fix))
  else: p('{:.{p}f}'.format(i, p=fix))
  if i is not s[-1]: p(', ')
 else:
  print(']')

During your visit to our site, NumWorks needs to install "cookies" or use other technologies to collect data about you in order to:

With the exception of Cookies essential to the operation of the site, NumWorks leaves you the choice: you can accept Cookies for audience measurement by clicking on the "Accept and continue" button, or refuse these Cookies by clicking on the "Continue without accepting" button or by continuing your browsing. You can update your choice at any time by clicking on the link "Manage my cookies" at the bottom of the page. For more information, please consult our cookies policy.