Exit slides Esc

Unit 4 — Prefix/Infix/Postfix Notation

Slide 1 of 58

  1. The problem: The Calculator With No Brackets

    Priya's grandfather keeps an old calculator in a drawer. It has number keys and the keys +, -, * (times), / (divide) and ^ (power), but no brackets and no = key. You type numbers and signs one after another, with a space between them, and the screen shows the answer.

    Grandpa types this and the screen shows 10:

    6 8 4 2 - / +

    Priya is puzzled. Where did the 10 come from, when there is no = and no brackets?

  2. At the same time, her friends Maya and Leo are arguing about a sum on the board: 8 - 3 - 2. Maya says it is 3. Leo says it is 7, "because 3 − 2 is 1, and 8 − 1 is 7". Who is right, and why could the same argument never happen on Grandpa's calculator?

    And a last puzzle: what exactly should Priya type to work out 2 * (9 - 4) + 6 / 2 on Grandpa's calculator?

  3. No computer is needed, only pencil and paper. By the end of Lesson 1 you can answer all three. Lessons 2 and 3 go further: letters and long expressions, a stack to keep track by hand, and Python programs that evaluate and convert expressions for you.

    • Elementary and above: read the same expression in infix, prefix and postfix, and evaluate prefix and postfix by hand.

    • Elementary and above: convert infix to prefix or postfix by bracketing, and convert back again.

    • Junior and above: handle longer expressions with letters and powers, and convert directly between prefix and postfix.

    • Junior and above: evaluate expressions with a stack, by hand and in Python.

  4. Lesson 1 — Three ways to write the same sum

    Division: Elementary and above. This whole lesson is pencil-and-paper work. It is everything the ACSL Elementary Prefix/Infix/Postfix test asks, and it is the starting point for every other division.

  5. Infix, prefix and postfix

    The way you write sums at school puts each operator between its two numbers: 3 + 4. That is called infix notation ("in" the middle).

    There are two other ways to write the same sum.

    Notation Where the operator goes 3 + 4 is written
    infix between the two numbers 3 + 4
    prefix before the two numbers + 3 4
    postfix after the two numbers 3 4 +

    Prefix is also called Polish notation, after the Polish mathematician Jan Łukasiewicz who invented it, and postfix is Reverse Polish notation. Grandpa's calculator uses postfix.

  6. The numbers (and later, letters) are called operands. The signs are operators. In all three notations the operands stay in the same order: only the operators move. Tokens (each number or operator) are written with one space between them, so 12 3 + means twelve plus three.

  7. The five operators

    Operator Meaning Example
    + add 3 + 4 is 7
    - subtract 9 - 4 is 5
    * multiply 3 * 4 is 12
    / divide 8 / 2 is 4
    ↑ power 3 ↑ 2 is 3 × 3 = 9

    The power sign has two spellings. The ACSL Elementary test writes it ^, as in 3 ^ 2. The other divisions' tests, and this book, write ↑, as in 3 ↑ 2. Both mean the same thing, and on a keyboard you type it as ^. This book always answers with ↑.

    On the Elementary test every number is a single digit, you only ever divide by 1 or 2, and every power is 1 or 2 (5 ↑ 2 is 25, and 5 ↑ 1 is just 5).

  8. Infix needs rules: PEMDAS

    An infix sum only has one right answer because everyone agrees on the order of operations, often remembered as PEMDAS:

    1. Parentheses (brackets) first;

    2. then Exponents (powers, ↑);

    3. then Multiplication and Division;

    4. then Addition and Subtraction.

    Multiplication and division are on the same level, and so are addition and subtraction. Operators on the same level are done from left to right.

  9. Example 1. 8 - 3 - 2: both operators are on the same level, so go left to right. 8 − 3 = 5, then 5 − 2 = 3. Maya is right. Leo worked out 8 - (3 - 2), which is a different sum.

    Example 2. 8 / 2 * 2: left to right, 8 / 2 = 4, then 4 × 2 = 8 (not 8 / 4 = 2).

  10. Example 3. 6 + 8 / (4 - 2): brackets first, 4 − 2 = 2; then divide, 8 / 2 = 4; then add, 6 + 4 = 10.

    Prefix and postfix need no brackets and no PEMDAS. The position of each operator already says which numbers it works on, so there is nothing to argue about. That is the answer to the second puzzle.

  11. Evaluating postfix

    To find the value of a postfix expression:

    1. Find the first operator from the left.

    2. Apply it to the two numbers just before it: the left one is the first number of the sum, the right one is the second.

    3. Replace those three tokens by the answer, and repeat until one number is left.

    Example 4. Grandpa's 6 8 4 2 - / +.

    Step Expression What happened
    start 6 8 4 2 - / +
    1 6 8 2 / + 4 2 - is 4 − 2 = 2
    2 6 4 + 8 2 / is 8 / 2 = 4
    3 10 6 4 + is 6 + 4 = 10
  12. That is the calculator's 10, and the first puzzle is solved: it is exactly 6 + 8 / (4 - 2) from Example 3.

    Example 5. 4 2 3 * +: the first operator is *, so 2 3 * = 6, giving 4 6 + = 10.

    Watch out: order matters for -, / and ↑. 9 4 - is 9 − 4 = 5, not 4 − 9. The number that comes first is always the one on the left of the operator.

  13. Evaluating prefix

    In prefix each operator comes before its two numbers.

    1. Find an operator that is followed straight away by two numbers.

    2. Apply it to those two numbers, in order.

    3. Replace the three tokens by the answer, and repeat.

    The easiest operator to start with is the last one (the rightmost), since it is always followed by two numbers.

    Example 6. * + 1 3 - 7 2

    Step Expression What happened
    start * + 1 3 - 7 2
    1 * + 1 3 5 - 7 2 is 7 − 2 = 5
    2 * 4 5 + 1 3 is 1 + 3 = 4
    3 20 * 4 5 is 4 × 5 = 20
  14. Example 7. + * 2 3 ↑ 4 2: ↑ 4 2 is 4 ↑ 2 = 16 and * 2 3 is 6, so the answer is 6 + 16 = 22.

  15. Infix to prefix or postfix: brackets first

    This method always works.

    1. Fully bracket the infix sum: put brackets round every single operator and its two operands, following PEMDAS. Each bracket then holds exactly one operator.

    2. Write the operands down in the same order.

    3. Take the brackets from the inside out (and left to right when two are equally deep), and move each operator to just after its two operands for postfix, or just before them for prefix.

    Example 8. Convert (7 - 3) * 2 + 8 / 2.

  16. Fully bracketed, following PEMDAS: (((7 - 3) * 2) + (8 / 2)).

    For postfix, the inside brackets first:

    Bracket Becomes
    (7 - 3) 7 3 -
    ((7 - 3) * 2) 7 3 - 2 *
    (8 / 2) 8 2 /
    the whole thing, joined by + 7 3 - 2 * 8 2 / +

    For prefix, the same brackets with each operator in front: (7 - 3) becomes - 7 3, then * - 7 3 2, then / 8 2, and the whole thing is + * - 7 3 2 / 8 2.

    Check: all three forms have the value 12.

  17. Example 9. The last puzzle: 2 * (9 - 4) + 6 / 2 is ((2 * (9 - 4)) + (6 / 2)). In postfix it is 2 9 4 - * 6 2 / +, and that is what Priya types. It evaluates to 10 + 3 = 13.

  18. Example 10. Same-level operators go left to right, so 9 - 4 - 2 + 1 is (((9 - 4) - 2) + 1), which in postfix is 9 4 - 2 - 1 + and in prefix is + - - 9 4 2 1.

    Check yourself: evaluate your answer and the original sum. If the values differ, something moved to the wrong place.

  19. Prefix or postfix back to infix

    Work in the other direction by scanning for a small piece you can undo.

    • In prefix, find an operator followed by two operands.

    • In postfix, find two operands followed by an operator.

    Replace that piece by a bracketed infix piece, which now counts as one operand, and repeat.

    Example 11. The postfix 2 3 * 4 2 ↑ +

    Step Expression
    start 2 3 * 4 2 ↑ +
    1 (2 * 3) 4 2 ↑ +
    2 (2 * 3) (4 ↑ 2) +
    3 ((2 * 3) + (4 ↑ 2))
  20. Prefix to postfix, and back

    To go from prefix to postfix, go through infix: first turn the prefix into a bracketed infix sum, then turn that into postfix.

    Example 12. The prefix + * 2 3 ↑ 4 2 from Example 7. To infix: ↑ 4 2 becomes (4 ↑ 2), * 2 3 becomes (2 * 3), and the whole thing is ((2 * 3) + (4 ↑ 2)). To postfix: 2 3 * 4 2 ↑ +. That is exactly the expression of Example 11, and both have the value 22.

  21. Postfix to prefix works the same way, through infix. Lesson 2 shows a quicker way that skips the infix step.

    Optional. This unit's folder also holds a small Python program, assets/l1.py, that evaluates a postfix expression. You do not need it for the Elementary test: everything in this lesson is done with pencil and paper. Students going on to Lesson 2 meet it there.

    Elementary checklist. You can now:

    • use PEMDAS, and go left to right on the same level;

    • evaluate a postfix expression;

    • evaluate a prefix expression;

    • convert infix to prefix and to postfix by fully bracketing;

    • convert prefix to postfix and postfix to prefix, through infix.

    That is the whole Elementary test. Exercises 1 to 9 are an Elementary practice test. Junior, Intermediate and Senior students continue with Lessons 2 and 3.

  22. Lesson 2 — Longer expressions, and a stack by hand

    Division: Junior and above.

  23. A self-checker for Lesson 1

    If you can run a Python program, this one evaluates a postfix expression, using exactly the "take the two numbers before the operator" idea of Lesson 1. Work each question by hand first, then use it to check yourself. Type the power sign as ^. It is saved as assets/l1.py; you do not need to understand the code yet, and Lesson 3 explains every line.

  24. Try it
    OPERATORS = ["+", "-", "*", "/", "^"]
    
    
    def apply(op, left, right):
        if op == "+":
            return left + right
        if op == "-":
            return left - right
        if op == "*":
            return left * right
        if op == "/":
            return left / right
        return left ** right
    
    
    def show(value):
        if value == int(value):
            return str(int(value))
        return str(value)
    
    
    stack = []
    top = 0
    for token in input().split():
        if token in OPERATORS:
            right = stack[top - 1]
            left = stack[top - 2]
            top = top - 2
            value = apply(token, left, right)
        else:
            value = int(token)
        if top == len(stack):
            stack.append(value)
        else:
            stack[top] = value
        top = top + 1
    print(show(stack[top - 1]))
  25. To run it, open a terminal in this unit's folder, type python assets/l1.py, then type a postfix expression such as 6 8 4 2 - / + and press Enter; it prints 10. You can also feed it a file: python assets/l1.py < assets/l1/3.in checks 5 2 ^ 6 2 / - and prints 22.

  26. Letters, big numbers and powers

    From Junior up, operands can be numbers of any size or letters standing for numbers, such as A B C. Letters are converted exactly like numbers: they are operands, and they never change order.

    The power ↑ sits above * and / in PEMDAS. So 2 * 3 ↑ 2 is 2 × 9 = 18, not 6 ↑ 2 = 36. The questions in this book never put two ↑ in a row without brackets, so you never have to decide which power goes first.

  27. Example 1. Convert (A + B * C) / (D - E) ↑ 2 to prefix and postfix.

    Fully bracketed: the ↑ binds (D - E) and 2 first, and the / is done last.

    ((A + (B * C)) / ((D - E) ↑ 2))

    Inside out: (B * C) → B C *, then (A + …) → A B C * +; (D - E) → D E -, then (… ↑ 2) → D E - 2 ↑; finally the /.

    • Postfix: A B C * + D E - 2 ↑ /

    • Prefix: / + A * B C ↑ - D E 2

    Watch out: the 2 in ↑ 2 is an operand like any other, so it keeps its place in the list of operands: A, B, C, D, E, 2.

  28. Prefix to postfix directly

    Going through infix works, but for long expressions a direct method is faster. Find an operator with its two finished operands, and rewrite that piece in the other notation inside square brackets. A bracketed piece counts as one operand from then on. When nothing is left to do, drop the brackets.

    Example 2. The prefix - * A + B C / D E to postfix. In prefix, a piece is an operator followed by two operands.

    Step Expression Piece
    start - * A + B C / D E
    1 - * A [B C +] / D E + B C → B C +
    2 - * A [B C +] [D E /] / D E → D E /
    3 - [A B C + *] [D E /] * A [B C +] → A B C + *
    4 [A B C + * D E / -] - [A B C + *] [D E /]

    So the postfix is A B C + * D E / -.

  29. Postfix to prefix is the same idea: in postfix a piece is two operands followed by an operator, and you rewrite it as [operator operand operand]. Run Example 2 backwards to see it.

  30. A stack: how a machine evaluates postfix

    A stack is a pile, like a pile of plates: you only ever put a plate on the top (a push) or take the top plate off (a pop).

    To evaluate postfix with a stack, read the tokens from left to right:

    • an operand: push it;

    • an operator: pop the top value (it is the right operand), pop the next one (the left operand), work out left operator right, and push the answer.

    At the end, the stack holds one value: the answer.

  31. Example 3. 9 3 5 + * 12 4 / -, with the stack written bottom to top:

    Token Action Stack after
    9 push 9
    3 push 9 3
    5 push 9 3 5
    + pop 5 and 3; 3 + 5 = 8 9 8
    * pop 8 and 9; 9 × 8 = 72 72
    12 push 72 12
    4 push 72 12 4
    / pop 4 and 12; 12 / 4 = 3 72 3
    - pop 3 and 72; 72 − 3 = 69 69

    The answer is 69. Writing the table is slower than the scanning method of Lesson 1, but it never loses track of a long expression, and it is exactly how a program does it.

    Watch out: the first value you pop is the right operand. For 72 3 - you pop 3 first, and the sum is 72 − 3, not 3 − 72.

  32. A stack for prefix: read from the right

    Prefix works the same way, reading the tokens from right to left. The one change: now the first value you pop is the left operand.

    Example 4. - * 2 + 3 4 / 9 3, read from the right:

    Token Action Stack after
    3 push 3
    9 push 3 9
    / pop 9 (left) and 3 (right); 9 / 3 = 3 3
    4 push 3 4
    3 push 3 4 3
    + pop 3 (left) and 4 (right); 3 + 4 = 7 3 7
    2 push 3 7 2
    * pop 2 (left) and 7 (right); 2 × 7 = 14 3 14
    - pop 14 (left) and 3 (right); 14 − 3 = 11 11

    The answer is 11.

  33. A stack in Python

    A Python list can be a stack. This book keeps a list stack together with a count top of how many values are on it, and never shrinks the list:

    • push a value: if top equals len(stack), append it; otherwise write it over the old value at stack[top]. Then add 1 to top.

    • pop: take 1 from top; the popped value is stack[top].

    • the top value is stack[top - 1].

    Values above top are just leftovers from earlier; the program ignores them.

  34. stack = []
    top = 0
    
    for value in [9, 3, 5]:
        if top == len(stack):
            stack.append(value)
        else:
            stack[top] = value
        top = top + 1
    print("top value:", stack[top - 1], "count:", top)
    
    top = top - 1
    right = stack[top]
    top = top - 1
    left = stack[top]
    print("popped", right, "then", left)
    
    value = left + right
    if top == len(stack):
        stack.append(value)
    else:
        stack[top] = value
    top = top + 1
    print("top value:", stack[top - 1], "count:", top)
    print("the list itself:", stack)

    Output

    top value: 5 count: 3
    popped 5 then 3
    top value: 8 count: 2
    the list itself: [9, 8, 5]
    
  35. After the two pops and one push, the stack holds 2 values (9 and 8), but the list still has 3 items: the 5 is a leftover above top. That is why every loop in this unit uses top, never len(stack), to know how many values are really on the stack. Try it with another list in place of [9, 3, 5], or another operator in place of the +.

  36. Put it together: this program evaluates a postfix expression and prints the stack after each token, just like the table in Example 3. Use it to check your own stack tables. An operator pops two values (right first, then left) by moving top down 2, and the loop at the end prints the values from stack[0] up to the top. It is saved as assets/l2.py.

  37. Try it
    OPERATORS = ["+", "-", "*", "/", "^"]
    
    
    def apply(op, left, right):
        if op == "+":
            return left + right
        if op == "-":
            return left - right
        if op == "*":
            return left * right
        if op == "/":
            return left / right
        return left ** right
    
    
    def show(value):
        if value == int(value):
            return str(int(value))
        return str(value)
    
    
    stack = []
    top = 0
    for token in input().split():
        if token in OPERATORS:
            right = stack[top - 1]
            left = stack[top - 2]
            top = top - 2
            value = apply(token, left, right)
        else:
            value = int(token)
        if top == len(stack):
            stack.append(value)
        else:
            stack[top] = value
        top = top + 1
        line = token + " :"
        for i in range(top):
            line = line + " " + show(stack[i])
        print(line)
  38. Run it from this unit's folder:

    python assets/l2.py < assets/l2/2.in

    The input 9 3 5 + * 12 4 / - prints the nine rows of Example 3, one per token, ending with - : 69. assets/l2/3.in holds 2 3 ^ 1 -, which shows a power on the stack.

  39. Lesson 3 — Evaluating and converting with Python

    Division: Junior and above.

  40. A postfix evaluator

    The stack method turns straight into a program. The function apply does one operation, and the loop pushes operands and handles operators. Python writes the power ↑ as **, and the program reads it as ^, the keyboard's spelling.

  41. OPERATORS = ["+", "-", "*", "/", "^"]
    
    
    def apply(op, left, right):
        if op == "+":
            return left + right
        if op == "-":
            return left - right
        if op == "*":
            return left * right
        if op == "/":
            return left / right
        return left ** right
    
    
    def evaluate_postfix(text):
        stack = []
        top = 0
        for token in text.split():
            if token in OPERATORS:
                right = stack[top - 1]
                left = stack[top - 2]
                top = top - 2
                value = apply(token, left, right)
            else:
                value = int(token)
            if top == len(stack):
                stack.append(value)
            else:
                stack[top] = value
            top = top + 1
        return stack[top - 1]
    
    
    print(evaluate_postfix("9 3 5 + * 12 4 / -"))
    print(evaluate_postfix("2 9 4 - * 6 2 / +"))
    print(evaluate_postfix("2 3 * 4 2 ^ +"))

    Output

    69.0
    13.0
    22
    
  42. The first line prints 69.0, not 69. In Python, / always gives a decimal number, even when the division is exact (12 / 4 is 3.0), and the .0 carries on into every later step. The answer to an ACSL question is written as a whole number when it is whole, so the program needs one more small function.

    def show(value):
        if value == int(value):
            return str(int(value))
        return str(value)
    
    
    print(show(69.0))
    print(show(13))
    print(show(15.5))

    Output

    69
    13
    15.5
    
  43. show compares the value with its whole-number part: if they are equal, it prints the whole number; if not, it prints the decimal. The self-checker assets/l1.py from the start of Lesson 2 is exactly apply, the loop of evaluate_postfix, and show, reading the expression with input(). Look back at it now: you can read every line.

  44. A prefix evaluator

    For prefix, walk the tokens from right to left with range(len(tokens) - 1, -1, -1), and remember that the first value popped is now the left operand.

  45. OPERATORS = ["+", "-", "*", "/", "^"]
    
    
    def apply(op, left, right):
        if op == "+":
            return left + right
        if op == "-":
            return left - right
        if op == "*":
            return left * right
        if op == "/":
            return left / right
        return left ** right
    
    
    def evaluate_prefix(text):
        tokens = text.split()
        stack = []
        top = 0
        for i in range(len(tokens) - 1, -1, -1):
            token = tokens[i]
            if token in OPERATORS:
                left = stack[top - 1]
                right = stack[top - 2]
                top = top - 2
                value = apply(token, left, right)
            else:
                value = int(token)
            if top == len(stack):
                stack.append(value)
            else:
                stack[top] = value
            top = top + 1
        return stack[top - 1]
    
    
    print(evaluate_prefix("- * 2 + 3 4 / 9 3"))
    print(evaluate_prefix("+ * 2 3 ^ 4 2"))

    Output

    11.0
    22
    
  46. The only two lines that differ from the postfix loop are the range going backwards and the swapped left and right. Swap them back and - * 2 + 3 4 / 9 3 gives a wrong answer: try it.

  47. Converting with a stack

    A stack can hold text as well as numbers. To turn postfix into prefix, push each operand as a piece of text; for an operator, pop two pieces and push one new piece, operator, left, right, joined with spaces. That is the square-bracket method of Lesson 2, done by a machine. It is saved as assets/l3.py.

  48. Try it
    OPERATORS = ["+", "-", "*", "/", "^"]
    
    stack = []
    top = 0
    for token in input().split():
        if token in OPERATORS:
            right = stack[top - 1]
            left = stack[top - 2]
            top = top - 2
            item = token + " " + left + " " + right
        else:
            item = token
        if top == len(stack):
            stack.append(item)
        else:
            stack[top] = item
        top = top + 1
    print(stack[top - 1])
  49. Run it from this unit's folder:

    python assets/l3.py < assets/l3/1.in

    The input A B C * + D E - / prints / + A * B C - D E. assets/l3/3.in runs Lesson 2's Example 2 backwards: A B C + * D E / - prints - * A + B C / D E. To go from prefix to postfix instead, read from the right, and push left, right, operator.

  50. Longer expressions and non-whole answers

    Division: Intermediate and above.

    Intermediate and Senior questions use longer expressions, and a division does not have to come out whole. The stack method is the same; just keep the fractions. Write a non-whole answer as a decimal. In this book every division ends after a few decimal places (halves, quarters, tenths and so on), never a repeating decimal such as 1/3.

    Example 1. 7 2 / 3 4 * +: 7 / 2 = 3.5, 3 × 4 = 12, and 3.5 + 12 = 15.5.

  51. Example 2. 3 4 ↑ 5 * 9 2 / 6 * - 8 /

    Piece Value
    3 4 ↑ 81
    81 5 * 405
    9 2 / 4.5
    4.5 6 * 27
    405 27 - 378
    378 8 / 47.25

    A fraction in the middle can still end in a whole answer: in 9 4 / 2 ↑ 16 *, the value 9 / 4 = 2.25, and 2.25 ↑ 2 = 5.0625, but 5.0625 × 16 = 81.

    Letters with values. A question may give values for the letters, such as A = 3 and B = 5. Replace each letter by its value, then evaluate as usual.

  52. Optional aside: expression trees

    Not assessed.

    An expression can also be drawn as a tree: each operator is a branch point with its left operand below-left and its right operand below-right. Here is (A + B * C) / (D - E) ↑ 2 from Lesson 2:

                /
             /     \
           +         ↑
          / \       / \
         A   *     -   2
            / \   / \
           B   C D   E

    Reading the tree in three orders gives the three notations:

    • prefix: the operator, then its left side, then its right side: / + A * B C ↑ - D E 2;

    • infix: the left side, then the operator, then the right side (with brackets);

    • postfix: the left side, then the right side, then the operator: A B C * + D E - 2 ↑ /.

    You will meet trees again later in the book; for now, the stack is all you need.

    • Elementary and above: postfix puts each operator after its two operands and prefix puts it before, so neither needs brackets: 6 8 4 2 - / + is 10.

    • Elementary and above: to convert infix, bracket every operation first, keep the operands in order, and take equal precedence left to right (8 - 3 - 2 is 3).

    • Junior and above: a stack evaluates postfix left to right: push each number, and let each operator pop two and push its result. For prefix, read from the right.

    • Junior and above: in Python, a list and a top count make that stack.

    You can now evaluate and convert between all three notations, by hand and with a program.