RPN Entry Order Monday, the 27th of July

When using an RPN (reverse polish notation) calculator, entry order matters. That is, the number of keystrokes and other properties of the evaluation depend on the path taken, even though the result is mathematically the same. In the following I will be using the following example to evaluate.

10𝜋2+191+11⋅sin(15)

Rewriting this problem in a flat algebraic form as used by many programming languages yields:

(10 * pi^2 + 19) / (1 - sqrt(11) * sin(15))

Which, if translated naïvely to RPN, as used on HP or derived calculators gives:

10 ENTER
π x² *
19 +
1  ENTER
11 √x
15 SIN *
+ /

That is more than is actually necessary!

A better form is:

π x²
10 *
19 +
11 √x
15 SIN *
1 + /

That saves us two words, or 12.5%. Not too bad.

In the rest of this page, I’ll be discussing how we can easily find the lowest needed stack depth for evaluating a specific expression.

Why?

But why do we care about keystrokes? Simply put, there are two main reasons besides plain time:

Errors
The more you type, the more errors you make. That is doubly true if you’re performing extra operations, straining yourself in the process. Additionally, more keystrokes means more to redo in case of a typo elsewhere.

Furthermore, as we will see in the next point more keystrokes generally means a deeper stack. That’s more variables to keep track of in your head at the same time.

Stack Depth
Generally speaking, less optimal ways of entering an expression also have worse stack characteristics – they need more space (= depth). This barely matters on the likes of the R47/C47 or modern PC-based RPN calculators where the stack has 8 or more levels, but for older calculators in the family of the HP12c/HP15c, this can quickly become important, especially as only the lowest entry of the stack is visible and thus knowing how much space is left depends solely on the user. Consider:

1023+5⋅16+𝜋
Naive:    #Stack   Optimized: #Stack
10 ENTER  (1)      5 SQRT      (1)
2 ENTER   (2)      3 +         (1)
3 ENTER   (3)      1/x         (1)
5 SQRT    (4)      2 *         (1)
+ /       (2)      16 *        (1)
16 *      (2)      π +         (1)
π +       (2)      1/x         (1)
/         (1)      10 *        (1)

This might not look like too bad of a difference, but the main difference lies in the stack depth written in parentheses. The first example reaches the maximum stack depth of the likes of the HP15c, that means that any error in entry would result in the loss of the initial 10 and very likely the user restarting the calculation.

Note though that in the second case the use of the sequence 1/x 10* would also be able to then complete that part of the calculation – more compact operations can also help in rescuing a partially erroneous calculation. However due to floating point imprecision that result might not always be the same.

How?

To get an understanding behind the general process for improving an RPN expression, let us rewrite our input into Lisp/S-expressions, that is, we transform the reverse polish notation to regular polish notation.

(/
  (+ (* (square (PI)) 10) 19)
  ((+ 1 (* (sqrt 11) (sin 15))))

When translating this to RPN, one has to start at the positions of deepest nesting inside the branch that is relevant. Two things one might immediately notice: all the positions we changed are nested deepest and involve calls to monadic functions, that is, functions that only take one argument. In this case these are square, sqrt and sin.

To summarise what can be seen from the S-expression form:

Why is this the case? This results from the way numeric entry fundamentally works on these machines. When typing in a number, one needs to signal to the calculator, that we’re finished with that particular number. There are two ways to do this: hitting ENTER or entering an operator, which, in addition to executing will also end entry.

Separating two numbers is necessary for diadic functions that take both of their arguments as literals, or for diadics that take one literal argument if, we begin with that argument.

Taking 10+sin(20), i.e. 10 ENTER 20 SIN + and 20 SIN 10 +

It immediately becomes clear why the right alternative is faster: one doesn’t have to (and cannot always) press ENTER after the result of the sine, since the monadic function already ends the input of 20. In fact, on the likes of the 15c, hitting ENTER after 10 is erroneous, since that will lead to an excessive 10 on the stack.

Exceptions

So far we only considered commutative operators like * and +, but the results slight change when we consider 10−𝜋2: 10 ENTER π x², π x² CHS 10 + or π x² 10 x<>y -

An additional CHS (change sign) or swap operation suddenly becomes necessary, as the order of the operands to - cannot be disregarded. The same applies to / too; its inverse that can be used like CHS is 1/x.

In fact, this is the reason operators like 1/x exist in the first place; consider the following problem:

3111∗𝜋2+10

The rules of efficiency demand we start at the deepest nesting, which is clearly the denominator. But then we need to exchange with a 3 at the end, which is not nested at all.

We type 111 SQRT π x² 10 + 1/x 3 * instead of 3 ENTER 111 SQRT π x² * 10 + / Even though this saves us no keystrokes (it would have if we had 1 in the numerator instead which is incredibly common) – this makes the expression more intuitive to type and decreases the dead (i.e. unused) stack depth during the majority of the calculation. Note that when the numerator (or the first argument to -) is a constant, this doesn’t need any extra keystrokes, it simply reorders them.

Constants

This mainly applies to π on traditional calculators, but if your calculator has a constant-store (like the R47), this applies here too. Since these keys output a full number, there is no need to hit ENTER. For 10+𝜋: 10 ENTER π + vs π 10 +

This tends to mainly happen with multiplication, since scaling constants by a factor happens all the time. Thus one of the classic beginners mistakes in RPN is calculating the circumference of a circle (with 𝑟 being the radius).

2 ENTER r * π * vs r π * 2 *

The first form matches the equations traditional form in algebraic notation 2𝑟𝜋 (Note that the form 2𝜋𝑟 also suffers from this), but the right hand side avoids all ENTER-s.

My Procedure

To summarize, when evaluating an expression: