After reading the definition, I made a simple Reverse Polish Notation (RPN) calculator in Python.
Originally it had just 4 operators (using import operator
and a lookup table) and only did integers. After looking at some example calculations, I amended it to work on floats and added a raising to powers. Then I saw some more advanced operations here and added math functions.
Owing to the large amount of math functions available, is there an easier way to include them without having to have math.<function>
in the operators lookup?
# Reverse Polish Notation calculator
# based on http://en.wikipedia.org/wiki/Reverse_Polish_notation
import math
import operator
ops = {'+':operator.add,
'-':operator.sub,
'*':operator.mul,
'/':operator.div,
'^':operator.pow,
'sin':math.sin,
'tan':math.tan,
'cos':math.cos,
'pi':math.pi}
def is_number(s):
try:
float(s)
return True
except ValueError:
pass
def calculate(equation):
stack = []
result = 0
for i in equation:
if is_number(i):
stack.insert(0,i)
else:
if len(stack) < 2:
print 'Error: insufficient values in expression'
break
else:
print 'stack: %s' % stack
if len(i) == 1:
n1 = float(stack.pop(1))
n2 = float(stack.pop(0))
result = ops[i](n1,n2)
stack.insert(0,str(result))
else:
n1 = float(stack.pop(0))
result = ops[i](math.radians(n1))
stack.insert(0,str(result))
return result
def main():
running = True
while running:
equation = raw_input('enter the equation: ').split(' ')
answer = calculate(equation)
print 'RESULT: %f' % answer
again = raw_input('\nEnter another? ')[0].upper()
if again != 'Y':
running = False
if __name__ == '__main__':
main()
Simple/straightforward test:
enter the equation: 6 4 5 + * 25 2 3 + / - stack: ['5', '4', '6'] stack: ['9.0', '6'] stack: ['3', '2', '25', '54.0'] stack: ['5.0', '25', '54.0'] stack: ['5.0', '54.0'] RESULT: 49.000000
Math functions test:
enter the equation: 5 8 2 15 * sin * + 2 45 tan + / stack: ['15', '2', '8', '5'] stack: ['30.0', '8', '5'] stack: ['0.5', '8', '5'] stack: ['4.0', '5'] stack: ['45', '2', '9.0'] stack: ['1.0', '2', '9.0'] stack: ['3.0', '9.0'] RESULT: 3.000000