Shriphani Palakodety

In Pursuit Of Truth and Beauty

Shriphani Palakodety header image 2

RPN Calculator – Keeping Boredom Away

January 14th, 2009 · 17 Comments · Daily life, Mathematics, python

Alright, those who know me well are bound to ask, 19 credit hours and you are bored? Answer: Yes. It is still the first week and we don’t seem to have gotten beyond the “introduce your loser self to the other non-interested members of the class” and since I have only 1 programming intensive course this semester, I should have lots of time to kill.

Well, my first script this semester is an RPN calculator. Totally useless for the vast majority of people out there but they know what to expect from someone who likes theoretical computer science.

So, I first began with a stack – in this case an array. I then keep populating it with numbers and every time the state of the stack changes, it prints out the current state.

If an operation is entered (only +, -, * and /), it performs the operation, replaces the appropriate positions in the stack and then prints out the current state.

Here is the code, Its been a while since I wrote any OOP stuff in Python and the “self” especially feels weird after an entire semester of Java…

#!/usr/bin/env python
#Author: Shriphani Palakodety
#Mail: shriphani@shriphani.com
#RPN Calculator

class Machine:
        def __init__(self, stack=[]):
                self.stack = []

        def modifyStack(self, element):
                ‘add to stack if input is float else run operation or complain’

                if self.isOperator(element):
                        self.operate(element)
                        self.printStack()
                elif self.isFloat(element):
                        self.stack.append(element)
                        self.printStack()

                else:
                        print "Only numbers and operators"

        def isFloat(self, char):
                ‘Checks whether the last item entered in the stack is a float or not’
                try:
                        float(char)
                except ValueError:
                        return False
                return True

        def isOperator(self, char):
                ‘Checks whether the last item entered in the stack is an operator or not’
                if char == ‘+’ or char == ‘-’ or char == ‘*’ or char == ‘/’:
                        return True
                else:
                        return False

        def operate(self, operator):
                ‘Perform the stated operation on the last two elements in the stack’
               
                operand1 = float(self.stack[-1])
                operand2 = float(self.stack[-2])

                self.stack.pop(-1)
                self.stack.pop(-1)

                if operator==‘+’:
                        self.stack.append(operand1+operand2)

                elif operator==‘-’:
                        self.stack.append(operand2-operand1)

                elif operator==‘*’:
                        self.stack.append(operand1*operand2)

                elif operator==‘/’:
                        self.stack.append(float(operand2)/float(operand1))

                else:
                        print "God only knows what operation you have typed in"
                        self.stack += [operand2, operand1]
                        self.printStack()

        def printStack(self):
                print self.stack

       
def kickOff():
        calc = Machine()
        while True:
                a = raw_input(‘Input: ‘)
                if a != :
                        calc.modifyStack(a)
                else:
                        calc.printStack()
                        raise SystemExit

print"Press Enter to Quit\n"
kickOff()
 

The calculator in action:

pal-179-083:~ shriphani$ python rpn.py
Press Enter to Quit

Input: 1
['1']
Input: 2
['1', '2']
Input: 3
['1', '2', '3']
Input: 4
['1', '2', '3', '4']
Input: 5
['1', '2', '3', '4', '5']
Input: +
['1', '2', '3', 9.0]
Input: h
Only numbers and operators
Input: -
['1', '2', -6.0]
Input:
['1', '2', -6.0]

In other news, I am really pissed with Picasa since I can’t see how many people have viewed my pics (http://picasaweb.google.com/shriphanip in case you are interested), I have begun filling my playlists with songs played at apple keynotes and in apple ads. Friends say this is an obsession with everything with the Apple stamp on it. I basically don’t care.

There has always been this one question bugging me since last semester. In Java:

 class Test
{
        public static void main(String[] args)
        {
                int a = 012345;
                System.out.println(a);
        }
}
 

When I run this:

pal-179-083:~ shriphani$ java Test
5349
pal-179-083:~ shriphani$

What is happening here?

Anyway, looking forward to this semester. Hope my GPA stays at 4.0

Tags:

17 Comments so far ↓

  • Paul Holt

    octal

  • Kevin McCravy

    For the Java question: By starting the literal with a zero you’ve designated it to be in octal, or base 8. In Python try “print oct(5349)”.

  • Michael Foord

    The same thing happens in Python. The leading 0 on your integer makes it an octal number.

  • DavidM

    That is octal format: “012345″

  • Anonymous

    A leading zero specifies an octal constant. Similarly, a leading 0x specifies a hex constant.

  • Dave Warner

    You are specifying an octal value (leading ‘zero’ flags value as an octal to the compiler) and println is outputting decimal.

  • Aaron

    In response to your question:

    12345 in octal is 5349 in decimal so perhaps Java takes a “0″ prefix to mean the number is in octal.

    This is just a guess as my Java experience ended when I started to learn Python (3+ years ago).

  • foo

    > int a = 012345;

    That would be octal. From http://java.sun.com/docs/books/tutorial/java/nutsandbolts/datatypes.html:

    “”"
    The prefix 0 indicates octal, whereas 0x indicates hexadecimal.


    int octVal = 032; // The number 26, in octal
    “”"

  • Jeff

    Oh, I know, Octal! ;-)

  • Marius Gedminas

    I won’t mention the word “octal” since nine people before me have already done so. ;-)

    A couple of suggestions for the Python code: the de facto standard indentation, also blessed by the official style guide (PEP 8) is 4 spaces per level, not 8.

    You can express the operator check more concisely as
    return char in ['+', '-', '*', '/']

    Also, ‘char’ is not a particularly good name since it may well be a multi-character string containing a floating point number.

    list.pop() defaults to popping the last item, so passing -1 is redundant.

    You’ve already converted both operands to floats when you extracted them from the stack (personally, I’d convert them when inserting into the stack, but whatever), so there’s no need for a repeated conversion where you’re implementing division. On the other hand, this may be a place where explicit is better than implicit.

    Machine.__init__ ignores the stack argument. Also beware of using mutable types such as lists for default argument values, you can easily end up sharing objects without intending to do so.

    I’d also use ‘return’ in place of ‘raise SystemExit’.

  • Marius Gedminas

    Small clarification: it was supposed to be “PEP 8″ (http://www.python.org/dev/peps/pep-0008/) followed by a closing parenthesis, and not a smiley at all.

  • xtian

    Octal octal, octal octal octal. Octal octal octal; octal.

    Oc tal octaaaaaaaaaaaallllllll!

  • Shriphani

    Marius:
    Thanks for your comments. Will keep them in mind.

    Everyone Else
    Thanks for answering my question.

  • Dethe Elza

    Someone suggested that the leading 0 will produce octal content in Python. While this used to be true, it has been fixed in more recent versions (I tested in Python 2.5.2). To interpret a string as an octal value in Python you now are expected to pass the base to int, thus:

    >>> int(’012345′)
    12345

    but

    >>> int(’012345′, 8)
    5349

    “Explicit is better than implicit” strikes again

  • Dethe Elza

    If you’re going to have folks talking about code, turning off automatic smiley’s would be a good step. The second example above should have ended with an eight (8) followed by a closing parenthesis.

  • rcriii

    May I suggest adding this to __init__:

    self.operations = {'+':lambda o1, o2:o1+o2,
                                  '-':lambda o1, o2:o1-o2,
                                  '*':lambda o1, o2:o1*o2,
                                  '/':lambda o1, o2:o1/o2,
                                  '^':lambda o1, o2:o1**o2}
    
    The isOperator becomes:
    def isOperator(self, char):
                    """Checks whether the last item entered in the stack is an operator or not"""
                    if char in self.operations.keys():
                            return True
                    else:
                            return False
    
    and Operate() becomes:
    
    def operate(self, operator):
                    """"Perform the stated operation on the last two elements in the stack"""
                    operand1 = float(self.stack[-1])
                    operand2 = float(self.stack[-2])
    
                    self.stack.pop()
                    self.stack.pop()
    
                        self.stack.append(self.operations[operator](operand1, operand2))
    

    And adding operators becomes quite easy.

  • Shriphani

    I’ve disabled automatic smileys. That shouldn’t be a problem anymore.

    Dethe Elza:
    Thanks a lot for mentioning that.

    rcriii:
    That looks cool. Thanks for posting your version.

Leave a Comment