Programming in User RPL
Programming in User RPL
Programming in User RPL
Version 2.1
Contents
1 Introduction 2
2 First concepts 3
2.1 Stack manipulation . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
2.2 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
3 Local variables 8
3.1 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
4 Conditional tests 10
4.1 Trues, Falses, Zeros and Ones . . . . . . . . . . . . . . . . . . . . . 10
4.2 Flags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
4.3 Basic conditionals: IF...THEN...ELSE . . . . . . . . . . . . . . 12
4.4 CASE structures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
4.5 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
5 Loop structures 18
5.1 Indefinite Loop Structures . . . . . . . . . . . . . . . . . . . . . . . 18
5.2 Definite loop structures . . . . . . . . . . . . . . . . . . . . . . . . . 19
5.3 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
6 Error handling 23
7 Getting Input 25
7.1 Enter input the by the Command Line: INPUT . . . . . . . . . . . . 25
7.2 Presenting options: CHOOSE . . . . . . . . . . . . . . . . . . . . . . 26
7.3 Input forms: INFORM . . . . . . . . . . . . . . . . . . . . . . . . . . 27
7.4 Getting key presses . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
7.5 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
8 Displaying output 33
8.1 Displaying message boxes: MSGBOX . . . . . . . . . . . . . . . . . . 33
8.2 Producing sounds . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
8.3 Displaying text strings . . . . . . . . . . . . . . . . . . . . . . . . . 33
8.4 Using FREEZE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
8.5 Clearing the display . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
A Answers to exercises 35
Chapter 2 — First concepts . . . . . . . . . . . . . . . . . . . . . . . . . . 35
Chapter 3 — Local variables . . . . . . . . . . . . . . . . . . . . . . . . . 36
Chapter 4 — Conditional tests . . . . . . . . . . . . . . . . . . . . . . . . 37
Chapter 5 — Loop structures . . . . . . . . . . . . . . . . . . . . . . . . . 39
Chapter 7 — Getting input . . . . . . . . . . . . . . . . . . . . . . . . . . 43
1
1 Introduction
If you’ve payed 270 bucks for a calculator, it should do something really nice. Well, it
does. It’s a programmable calculator, which mean you can “teach” it to do something it
does not automatically do. But in the HP48, with its complete and powerful program-
ming language and structure, allows more than simple programs that repeat keystrokes,
like in other calculators. You can create programs with graphics, user interfaces, and
much more.
In this tutorial, you’ll learn how to make simple (and some a bit more complicated)
programs in UserRPL, the programming language of the HP48. Most examples are
related to math, and most programs are totally useless: the calculator does the same the
program does automatically. They just examples, to demonstrate the concepts you’ve
learned.
A note about the exercises: some chapters have exercises. They are meant to be
done, not just skipped. If you don’t practice, how will you learn? There are answers
to all of them, but the solution I give is only one possibility in many cases. There are
many others. If your program worked, then you should consider the exercise as solved,
even if the answer I give is different or even more efficient. But compare my solution
to yours. Sometimes they may be completely different answers. Which one is more
efficient? Which one is faster? Which one is smaller? If you have a different solution
to a problem, send it to me at my e-mail: [email protected].
If you have found any error in this tutorial, be it a spelling error, an error in a
program, or anything else, please warn me at the above e-mail. I’d also like to hear
comments and suggestions.
2
2 First concepts
For 270 bucks, you should expect a calculator that does everything you need. Several
functions are already available, but probably you’ll soon need something the HP cannot
do automatically. Say you have to calculate the determinant of a symbolic matrix.
Since the HP has built-in support only for numerical matrices, you’ll have to calculate
it manually. If you need to do that only once, that’s OK, but what to do if you need
several calculations, always doing the same thing, pressing the same keys, only for
different inputs?
That’s why the HP48 is different from other calculators. It is programmable. It
means it can learn how to do something. In the example above, you could write a pro-
gram that calculates the determinant of a symbolic matrix when you give its elements.
So, to calculate a determinant, the only thing you would need to do is enter the ele-
ments and run the program. Want to calculate the determinant for different inputs? No
problem, just key them in and run the program again, and you’ll get the new results.
Basically, a programmable calculator can save you time.
On the HP48, programs are delimited by left and right guillemots (that’s the « and
» symbols.) To put enter those delimiters, press left-shift and minus. Inside, there is a
sequence of objects, separated by spaces. Depending on the object type, some action
is taken, according to table 1.
Object Action
Command Run
Number Put into stack
Algebraic Put into stack
String Put into stack
List Put into stack
Program Put into stack
Global name (between ’’) Put into stack
Global name (without ’’) Put into stack and automatically evaluated
Local name (between ’’) Put into stack
Local name (without ’’) Put into stack and automatically evaluated
Let’s see a simple example of a program. Suppose you have a 52-gallon cylindrical
water heater and you wish to determine how much energy is being lost because of poor
insulation. For that you can use the formula
q = hAT
where q is the heat loss from the heater (in btu per hour), h is the heat transfer coeffi-
cient (in our case 0.47), A is the total surface area of the cylinder (in our example 30)
and T is the temperature difference.
3
The values of h and A will remain constant in our case, but we want to calculate
the heat loss for various temperature differences. You could key in the values every
time and multiply them, but this task can be simplified with a very simple program.
Let’s create a program that calculates the heat loss for the heater when the temper-
ature difference is given in the stack. Type the following program, and press ENTER
(one more time: to get « » press Left-shift Minus):
« 30 * .47 * »
Let’s examine this program carefully. The first thing after the « opening program
delimiter is the number 30. All numbers are put into the stack, so the stack now contains
the temperature difference (which you entered) and 30, the surface area (put by the
program.) The next object is a command, *. It will be executed, multiplying the two
numbers in the stack. This will put in the stack the result of A × T . In sequence
there is another number, 0.47, that will be put into the stack. The last object is another
command, again *. In the stack there is now the result of the multiplication of A × T
by h, or hAT , which is the wanted result q.
Now let’s try the program and see if it works. If you have not already entered the
program, do it now. You should see the program in level one of the stack. To save
it in the memory, type ’HT’, press ENTER, then STO. Now press VAR. You should
see HT on the first menu key. Congratulations, you’ve just saved your first User RPL
program.
To try it, enter 15 and press the first softkey, corresponding to the just stored HT
program. You should get 211.5 in the stack. Now, if you wanted to calculate again for
a temperature difference of 18 degrees, just enter 18 and run the program again. You
should get 253.8.
To see how practical it would be if you had to calculate several times, calculate the
heat loss for temperature differences of 10, 12, 14, 16, 18 and 20. The answers are 141,
169.2, 197.4, 225.6, 253.8 and 282.
DUP Makes a copy of the object in level one. Example (in all subsequent examples,
the left side represents the stack before the command, and the right side shows
the stack after the command):
2: 2: a
1: a 1: a
DUP2 Makes copies of the objects in levels one and two. Example:
4
4: 4: a
3: 3: b
2: a 2: a
1: b 1: b
DUPN Makes copies of n objects, starting at level two. n is given in level one. Exam-
ple:
6: 6: a
5: 5: b
4: a 4: c
3: b 3: a
2: c 2: b
1: 3 2: c
DROP Drops (ie, removes) the object in level one. Example:
2: a 2:
1: b 1: a
DROP2 Drops the objects in levels one and two. Example:
3: a 3:
2: b 2:
1: c 1: a
DROPN Drops n objects from the stack, starting at level two. n is given in level one.
Example:
5: a 5:
4: b 4:
3: c 3:
2: d 2:
1: 3 1: a
OVER Returns a copy of the object in level two. Example:
3: 3: a
2: a 2: b
1: b 1: a
PICK Returns a copy of the object in level n+1. n is given in level one. Example:
4: a 4: a
3: b 3: b
2: c 2: c
1: 3 1: a
SWAP Exchanges levels one and two. Example:
2: a 2: b
1: b 1: a
5
ROLL Moves the object in level n+1 to level 1. As usual, n is in level one. Example:
5: a 5:
4: b 4: b
3: c 3: c
2: d 2: d
1: 4 1: a
ROLLD Moves the object in level two to level n+1. Example:
5: a 5:
4: b 4: d
3: c 3: a
2: d 2: b
1: 4 1: c
ROT Moves the object in level three to level one. This command is equivalent to
3 ROLL. Example:
3: a 3: b
2: b 2: c
1: c 1: a
DEPTH Returns the number of elements in the stack. Example:
4: 4: a
3: a 3: b
2: b 2: c
1: c 1: 3
Now let’s see another very simple program. It calculates the hypotenuse of a right
triangle, given the two legs in the stack.
√
« SQ SWAP SQ + »
Let’s examine this program closely. First, it squares the number in level one. Then
it swaps levels one and two, and squares the object now at level one, the other side of
the triangle, which was before in level two. The program then adds them, and takes the
square root. Simple, isn’t it?
2.2 Exercises
1. What happens when the following programs are run?
(a) « « « 1 2 + » » EVAL »
(b) « « « 1 2 + » EVAL » »
(c) « « « 1 2 + » EVAL » EVAL »
(d) « « « 1 2 + » » EVAL EVAL »
(e) « « 1 « 2 + » » EVAL »
(f) « « 1 « 2 + » EVAL » EVAL »
6
2. Design a program that, when the radius of a sphere is in level one, calculates its
volume. (V = 43 πr3 )
4. Write a program that does the inverse conversion (that is, from Celsius to Fahren-
heit).
6. Write a program that does the same thing as the above, but now using the formula
RP = RR11+R R2
2
, derived by isolating RP in the above formula.
a b
7. Write a program to calculate the determinant , assuming a, b, c and d
c d
are in the stack, in this order.
8. Write a program to calculate the distance of two points (x1 , y1 ) and (x2 , y2 ),
assuming x1 , x2 , y1 and y2 are in the stack, in this order.
9. Write a program to find one root of a quadratic equation, given a, b and c in the
stack.
10. Modify the above program so that it finds both roots of the equation.
11. Write a program to find the surface area of a rectangular box, using the equation
S = 2(hw + hd + wd).
7
3 Local variables
Let’s examine again the program given at the end of the last chapter, the one that
calculates the hypotenuse of a right triangle:
√
« SQ SWAP SQ + »
In the above program, each of the two inputs is used only once, so stack manipula-
tion is not complicated. But in some cases the inputs are used many times, so keeping
the stack organized can be quite difficult, and fetching a specific value is something
complicated. So, instead of using lots to commands to get the element you want, why
not store it somewhere, and them simply recall item when need arises? It would be a
lot easier.
To do that, you could use variables. Just enter a name, and use the STO command,
and it will be stored. It can later be recalled with RCL. But this brings some problems:
what if the user already has a variable with the name you want to use? And you must
take care to erase all variables used when the program ends. But what happens if the
program terminates unexpectedly, because of an error, for example? The user’s VAR
menu would be full of unnecessary stuff.
To help solve this problems, the HP48 calculator has a nice feature called local
variables. They work like normal variables, but they don’t appear in the VAR menu,
they are purged automatically when the program ends, they can’t be accessed by the
user and there is no problem in using a name that’s already a user’s variable.
Basically, one could say that local variables can exist only when a program is run-
ning and are accessible only to the program running, and any other programs called by
that program.
Local variables are created with the → command (the arrow is above the 0 key.)
The use is very simple: anywhere you want, use → followed by as many names of
variables you want, separated by spaces. The value will be taken from the stack and
stored in the variables.
Let’s clarify the above: suppose you have 1, 2 and 3 in the stack, in this order. If
you use → a, the local variable a will now contain the value 3. If you use → a b,
then a will contain 2 and b will contain 3. Finally, if you use → a b c, a will contain
1, b, 2 and c, 3.
OK, but how do I use this nice feature in a program? Very simple: add the →
command followed by the variable names and then either an algebraic expression that
will be evaluated substituting any local variables by their values or a program that will
be run, where you can use local variables as any other variable.
Let’s see an example: the above hypotenuse program could be written this way:
√
« →a b ’ (aˆ2+bˆ2)’ »
using algebraic notation or
√
« → a b « a SQ b SQ + » »
using a sub-program.
In this case, the first version (without local variables) is more efficient. But in
more complicated cases, local variables generally much better. At least, they make the
8
programs easier to understand, because you can see what’s being done, and not a lot
of stack manipulation commands such as SWAP 4 PICK OVER ROT ROT DUP.
However, you must know how the stack works, and the basic stack manipulation com-
mands before you go further in this tutorial. Alas, by this time, you should already
know them. If you don’t, go back to the previous chapter and learn what they do.
3.1 Exercises
1. Given a, b, u, c, d and v in the stack, write a program to solve the system
ax + by = u
cx + dy = v
du − bv av − cu
x= and y=
ad − bc ad − bc
2. Write a program, using local variables, to calculate the determinant of the matrix
a b c
d e f
g h i
using:
3. Write a program to calculate the inverse matrix of the matrix in the previous
exercise.
9
4 Conditional tests
One of the most powerful abilities of the HP is that programs can make decisions,
and execute actions based on these decisions. Of course it can’t, for example, choose
a good wine for you, but it could recommend the type of wine based on the type of
meat. This kind of decision, based on some given factor (type type of meat) is called
conditional, and is what we’ll see in this chapter. But before we start studying HP48
commands, let’s study a bit of Boolean algebra. It’s not going to hurt so much.
A A
0 1
1 0
The next operation we’ll see is AND. It is represented in the HP48 by ’A AND B’
and in textbooks by A ∧ B, A.B or simply AB. The AND function is true only if both
inputs are true. Its truth table is shown in table 3.
A B A.B
0 0 0
0 1 0
1 0 0
1 1 1
The third function is OR. As you might have guessed, the HP48 represents it as ’A
OR B’. The textbook representations are A ∨ B or A + B. This function is true if at
least of the inputs is true. See table 4 for the truth table.
10
A B A+B
0 0 0
0 1 1
1 0 1
1 1 1
Last, but not less important, there is XOR, which stands for eXclusive OR. It returns
true if the inputs are different. You’ll see it represented on the HP48 as ’A XOR B’
and in textbooks as A∨B or A ⊕ B. Its truth table is in table 5.
A B A⊕B
0 0 0
0 1 1
1 0 1
1 1 0
XOR is derived from the other functions. There are several ways to represent it
using only the first three operations. One of them is
A ⊕ B = ĀB + AB̄
That was all you needed to know about Boolean algebra. But before we really start
programming, let’s see a little more theory.
4.2 Flags
A flag is like a reminder. If you had to remember to, say, pick up dinner on the way
home, you would do something as a reminder to yourself, like tying a string to your
finger. OK, you would never do that, but this is just an example.
Sometimes, a program also needs to remember something. But a program can’t tie
a string to its finger. Alas, a program doesn’t have fingers. But since anatomy is not one
of my favorite subjects, let’s stop here. Back to programming, what could a program
do to remember something?
The answer is: storing some information in some place that can be read back later.
A normal (or local) variable could be used, but there are better things: flags. A flag is
like a variable, but can only contain two values: set and clear. Sounds like the boolean
thing above, doesn’t it?
The HP48 has 128 flags. Of these, 64 are reserved for its own use (not all are
used, however.) You can change their value, but this would mess the way the calculator
11
operates. For example, system flag 40 controls the the clock display. If your program
altered it, it would also change the displaying of the clock.
Because of this, there is another group of flags: the user flags. These 64 flags aren’t
used by the HP48. You can use them to do whatever you want.
The 64 system flags are represented by negative numbers, and the user flags by
positive numbers. So, -40 means system flag 40, and 55, user flag 55.
OK, but what can I do with flags? Simple: instead of tying a string to your finger to
remember to pick up dinner, set flag 4 (or any other.) Then, later, see whether the flag
is set. If it is, then pick up dinner; otherwise don’t. A program does exactly that, but to
remember other things (after all, calculators don’t eat.)
There are several commands to work with flags. They set flags, clear flags, and
return information about whether a flag is set or clear. They are summarized in table 6.
Command Action
SF Sets the flag specified in level 1
CF Clears the flag specified in level 1
FS? Returns 1 if the flag is set; 0 otherwise
FC? Returns 1 if the flag is cleared; 0 otherwise
FS?C Returns 1 if the flag is set; 0 otherwise, then clears flag
FC?C Returns 1 if the flag is cleared; 0 otherwise, then clears flag
RCLF Puts a list with the values of all flags in the stack
STOF Sets the flags according to the list in the stack
First, the test condition will be evaluated. If the result is true (ie, non-zero),
then the commands between THEN and END will be executed. Otherwise, they will be
skipped and execution will continue after END.
This structure has another clause, that allows execution of certain commands only
if the test condition is false (ie, zero). The new form is:
12
actions to be taken if condition is true
ELSE
actions to be taken if condition is not true
END
»
OK, in theory that’s easy to understand. But in practice, how can one use that?
Normally, we use comparison commands. They are: == (yes, to check equality you
must use == and not just =), <, >, 6=, ≤ and ≥. All take two arguments from the stack,
and return 1 if the condition is true and 0 if not. Ready for THEN. You can use AND
and the like to check for multiple conditions.
Let’s see a simple example of a program using IF structures. The program takes
three numbers from the stack, and returns the smallest of them.
(In User RPL, @ represents a comment. Everything after it until the end of the line
is ignored.
« →x
« IF 1 == THEN
"One"
ELSE
IF x 2 == THEN
"Two"
ELSE
IF x 3 == THEN
"Three"
ELSE
IF x 4 == THEN
"Four"
13
ELSE
"Other"
END
END
END
END
»
»
The method above works, but is quite inefficient. Notice that the IF’s look like
a stairway, descending each time more. There is a structure that makes this kind of
structure much more efficient: the CASE structure. The above program, rewritten to
use CASE would be:
« →x
« CASE
x 1 == THEN
"One"
END
x 2 == THEN
"Two"
END
x 3 == THEN
"Three"
END
x 3 == THEN
"Four"
END
"Other"
END
»
»
CASE
test clause 1 THEN
set of actions 1
END
test clause 2 THEN
set of actions 2
END
.
.
.
test clause n THEN
set of actions n
END
14
default set of actions
END
You can have any number of test clauses. When one evaluates to true (non-zero),
the corresponding set of actions is executed, until END. The rest of the CASE structure
is skipped until another END. If one clause evaluates to false (zero), the set of actions
is skipped until the first END, and the next clause is evaluated. If none of the clauses
evaluate true, the default action are taken. Note it isn’t necessary to include a default
set of actions.
4.5 Exercises
1. What’s the value of each of the following expressions?
(a) 0 ∧ 1 ∨ 0
(b) 1 ∧ 1 ∨ 0 ∧ ¬0
(c) (1 ⊕ 1) × 1 + 1
(d) (1 ⊕ (1 × (0 × 0 ⊕ 1))) ⊕ (1 + (0 × 1))
2. Assuming a = 0, b = 1, c = 1 and d = 0, what is the value of the expressions?
(a) a ∧ (¬b)
(b) a + b ⊕ d
(c) c + (d + (a + (c × (a ⊕ d))))
(d) (b ⊕ c) × (c + (a × b) ⊕ c)
3. Supposing the variables a, b, c, d and e contain, respectively, 127, 10, 5, 0 and
1, which do each of the following programs return?
(a) « d NOT »
(b) « d e AND »
(c) « a b > b c < OR »
(d) « a b < NOT »
(e) « d e AND a b == OR »
(f) « d e XOR a b < AND »
(g) « a b + c < d AND e XOR d NOT AND »
(h) « a b + c b / * 3 == a b OR NOT AND »
4. Which value will be returned when this program is run?
« 0 1 0 2.5 3.5 → a b c x y
« IF c x y + r > a NOT b AND OR OR THEN
0
ELSE
15
1
END
»
»
« →a b c
« IF a THEN
Command1
ELSE
IF b THEN
IF c THEN
Command2
ELSE
Command 3
Command 4
END
END
END
Command5
»
»
« 32 2 5 → a c h
« a 5 xroot c 3 4 / * → b j
« IF b j > THEN
8 h 6 SQ c / / *
ELSE
a h a / + h -
END
»
»
»
7. Write a program that toggles the value of a flag (ie, if it is set it is cleared, and
vice-versa) specified in level one.
16
8. Write a program that reads a flag number and a true/false from the stack. It it’s
true, it sets the flag, if not is clears the flag.
9. Write a program that reads three numbers form the stack and outputs them in
increasing order.
10. Write a program that, given the month, day and year, in this order, calculates
the day of the week, and outputs its name (“Sunday”, “Monday”, etc.) Use the
formula
jak jsk
dw = b2.6m − 2c + + + d + a − 2s mod 7
4 4
where
17
5 Loop structures
In the previous chapter, you learned some of User RPL control structures: the condi-
tionals. They allow part of a program to be executed only if a certain condition is met.
Now, we’ll see other types of control structures: the loop structures. They allow part
of a program to be executed more than once.
WHILE
test condition
REPEAT
code to be repeated
END
« 0 @ Initial sum
100 @ First number
→ sum n @ Save in variables to make things simpler
« WHILE
n 200 ≤
REPEAT @ Repeat while the number hasn’t reached 200
n ’sum’ STO+ @ Increment sum
’n’ 2 STO+ @ Yes, STO+ accepts its arguments in any order
END
sum @ Output the sum
»
»
18
DO
code to be executed
UNTIL
test condition
END
The code to be executed will be executed at least once, until test con-
dition evaluates true.
A note valid for both forms of loops. If you use something like
the program will be executed until your batteries drain completely or until it is
stopped by the user. So be careful to always put a condition to stop the loop.
Now let’s see how the above program would look like rewritten with DO. The only
change is that the test condition has been reverted.
« 0 100 → sum n
« DO
’sum’ n STO+
2 ’n’ STO+
UNTIL
n 200 >
END
sum
»
»
START reads to numbers from the stack, the initial number and the final number.
Then, the commands to be executed are executed. When NEXT is reached, the
initial number is incremented by one. If it is smaller than or equal to the final number,
then the commands will be executed again. If it is greater, then execution will continue
after NEXT.
The second type of definite loop structure is the FOR...NEXT loop. It is exactly
like START, with one difference: you can access the number of that execution and use
it as a normal variable. The syntax is:
19
start stop FOR var
commands to be executed
NEXT
The variable can have any name, and it works like any local variable. You can even
assign a new value to it. Traditionally, the variable is called i, j or k, but this is just a
convention.
In both kind of loops, you can change NEXT by increment STEP. The differ-
ence is that the count will be incremented by increment instead of 1.
Now let’s see our program in using a FOR loop:
« 0 @ Initial sum
100 200 @ Goes from 100 to 200
FOR i @ The current number is i
i + @ Increment sum by i
2 STEP @ Increment count by 2, since we want only even numbers
»
5.3 Exercises
1. Running the following program, which results do you get?
« { } 10
DO
DUP 1 - 3 ROLLD SQ + SWAP
UNTIL
DUP 1 ==
END
DROP
»
2. Modify the above program to use a WHILE structure (change as little as possi-
ble).
5. A radioactive chemical element loses half of its mass every 50 seconds. Given
the initial mass (in grams) in the stack, write a program to determine the time
necessary for the mass to get lass than 0.5 grams. Output the final mass and the
time in hours, minutes and seconds in the form "xh ymin zs".
20
6. Write programs to calculate the following sums:
1 3 5 7 99
(a) S = + + + + ··· +
1 2 3 4 50
21 22 23 250
(b) S = + + + ··· +
50 40 48 1
37 × 38 36 × 37 35 × 36 1×2
(c) S = + + + ··· +
1 2 3 37
1 2 3 4 10
(d) S = − + − + ··· +
1 4 9 16 100
1000 997 994 991 853
(e) S = − + − + ··· −
1 2 3 4 50
480 475 470 465 430
(f) S = − + − − ··· +
10 11 12 13 20
7. The following programs calculate sums of fractions. Write the sums as in the
above exercise, and also using sigma notation.
(a) « 0 DUP
14 FOR a
2 a ˆ 15 a - SQ /
-1 a ˆ * +
NEXT
»
(b) « 100
1 99 FOR b
100 b - b ! +
NEXT
»
(c) « 63
1 31 FOR i
63 i 2 * - i ! / +
NEXT
»
(d) « 1
2 20 FOR j
j ! 2 j ˆ 1 - /
-1 j ˆ * -
NEXT
»
21
9. Write a program that calculates the value of π, with a precision of 0.01. Use DO
and:
4 4 4 4
π = 4 − + − + + ···
3 5 7 9
10. Write a program that, when x is in the stack, returns ex , with a precision of
10−11 . Use WHILE.
x2 x3
ex = 1 + x + + + ···
2! 3!
11. Supposing x is in the stack, write programs to calculate the following sums:
1 1 1 1
(a) S = 1 + 2 + 3 + 4 + ··· + x
x2 x4 x6 x40
(b) S = x − 3! + 5! − 7! + · · · + 41!
1 2 3 x−1 x
(c) S = x + x−1 + x−2 + · · · + 2 + 1
12. Write a program that calculates the approximate square root of a number Y in
the stack, using Newton-Raphson’s method:
√
• the first approximation of Y is X0 = Y2
2
Xn +y
• the successive approximations are Xn+1 = 2Xn
13. Modify the above program so that it calculates the square root with a precision
of 10−11 .
f (Xn )
Xn+1 = Xn −
f 0 (Xn )
Assume the equation is in level three, the variable in level two and an initial
guess X0 is in level one. Calculate 30 approximations.
15. Modify the above program to search for a root with a precision specified by the
user in level one. All other inputs are shifted one level up.
22
6 Error handling
The HP48 User RPL programs are safe. Error handling is done automatically and the
programmer doesn’t have to worry about that. And, if some error condition occurs,
for example, if there aren’t enough arguments for a command, the only thing that will
happen is that an error beep will be heard (unless disabled by the user) and a message
will be displayed. The program will be stopped and the local variables will be removed.
There is no reason to worry about that.
However, sometimes it is necessary to worry about errors that might happen. If
your program, for example, needs a positive number as input, but a negative number
is entered, probably no error will occur in the program, but the result might be wrong
or meaningless. Because of this, there are some structure to handle errors or generate
errors.
The first of these is IFERRR...THEN...ELSE. It’s syntax is:
IFERR
detection clause
THEN
clause if error
ELSE
normal clause
END
« IFERR
1 9 FOR i
i
IF i 5 > THEN
0 DUP /
END
NEXT
THEN
END
»
23
But what if the program must take different actions based on the kind of error
that occurred? Suppose the program should do something if there was an “Undefined
Result” error and another action if there was an “Infinite Result” error. How can this
be done? With the commands ERRN, ERRM and ERR0.
The first, ERRN, returns the number (in hexadecimal string format) of the last error.
You can find a table of error values and their messages in Appendix B of the HP48
manual. ERRM returns a string with the error message. And ERR0 clears the last error.
Last but not less important than the others, there is the command DOERR. As the
name says, it is used to produce an error. It accepts different kinds of arguments: the
number of the error (either as a real number or as an hexadecimal string), a string with
a custom message, or 0. If you give a number (different from 0), that error will be
generated. If you give a string, that string will be shown in the status area. And 0 can
be used to stop a program, with no error message.
24
7 Getting Input
The most simple and obvious way of getting input for HP programs is the stack. The
user should put the arguments in the stack, and the results are returned to the stack.
However, sometimes this is not the best way. When there are many arguments, it may
be difficult for the user to remember the order, the type, and so on. So, there are better
ways of getting inputs. And so there are better ways of displaying output, which we’ll
see on the next chapter.
– A Greek alpha symbol (alpha left-shift a) will start the editor with the al-
phabetic keyboard on. This is very useful if the user is supposed to enter a
string.
– ALG will cause the editor to start with algebraic entry mode on.
– V will check the syntax of the entire command line when ENTER is pres-
sed, in the same way that the command line editor normally does, disallow-
ing an edit if there is an RPL syntax error.
INPUT returns what the user entered as a string. Normally, you would use OBJ→
to make it the way you need, for example a real number.
When the user presses CANCEL the first time during INPUT, the input line is
cleared. If the user presses CANCEL again, the rest of the program is canceled.
An example of a program using INPUT:
25
« "Enter A, B, C"
":A: :B:
INPUT
»
26
« "ANGLE MODE" @ Title
{ { " Degrees" DEG }
{ " Radians" RAD }
{ " Gradians" GRAD } } @ Items
1 @ Initial position
IF CHOOSE THEN EVAL END
»
• "label"
• { "label" "help" }
• { "label" "help" type1 type2 ... typen }
• { }
"label" is a string which will server as the title of the field, and which will be
displayed near the field. "help" is the text that will be displayed on the bottom line
when the field is specified (which should be a specification of what the field means.)
The type specifications are zero or more real numbers representing the types of objects
allowed in the field. If unspecified, all types of objects are valid. You can find a
list of object types in Appendix H of the manual, under command TYPE. If a field
specification is an empty list, the field immediately to the left is expanded to occupy
the unspecified field space.
The format specification is one of the following objects:
• { }
• columns
• { columns }
• { columns width }
Where columns is the number of columns that the form has. The default value is
one. width is the tab width between the left edge of each title and each field. This
allows a vertical alignment of the fields. The default is three.
27
The reset and initial values are either empty lists or list containing exactly one
object for each field. These values will be used when one (or all) the fields are reset, or
the first time the display is shown. If you want a field to be left blank, specify NOVAL
as its value.
If the user filled in the form, a list with the values will be returned to level two, and
1 (true) to level one. The the form was canceled, 0 (false) will be returned to level one.
A field that was left blank will be returned as NOVAL.
Let’s see an example of INFORM, because I’m sure you didn’t understand a thing
of the above. But you will understand if you see an example. The program will display
a dialog box like the one in picture 2, and will then calculate the distance of the points
if the user doesn’t cancel the form.
Now, let’s change a little our program, so that it displays with two columns, like
the image shown in picture 3.
28
Figure 3: INFORM with two columns
2 @ Two columns
{ } DUP @ No reset or initial values
IF
.
.
. @ The rest is equal
»
Plane Meaning
1 No modifier
2 Left-shift
3 Right-shift
4 Alpha
5 Alpha and left-shift
6 Alpha and right-shift
This way, MTH is key 21.1, RCL is key 32.3, x2 is key 44.2, and so on.
The following program will wait for a key, and exit if ENTER is pressed:
« 0 WAIT
IF
51.1 ==
THEN
KILL
29
END
.
.
. @ Rest of program
»
Another command related to keys is KEY (no comments.) It is used in loops, when
you want a loop to stop when a key is pressed. If no key is pressed while this command
runs, it will return 0, otherwise it will return the code of the key. But the code contains
no plane information, because the modifier keys also return a value (and thus probably
stop the loop). The following program will loop until a key is pressed:
« DO
.
.
. @ Your code here
UNTIL
KEY
END
»
7.5 Exercises
1. Using three INPUTs, write a program to calculate the roots of a quadratic equa-
tion, return the values on the stack. The user should be prompted for a, b and
c.
2. Write a program that uses INFORM to let the user enter a, b and c, and calculates
the roots of the quadratic equation. The program then uses INFORM again to
display the results. The screens should be like the ones in pictures 4 and 5.
3. Write a program that creates a screen like the one shown in pictures 6 and 7 (see
the different help) and then solves the system
ax + by = u
cx + dy = v
30
Figure 5: Output screen for exercise 2
31
4. Write a program that creates a screen like the one in picture 8 and calculates the
inverse matrix. After calculations are done, use a screen like the input one to
give the results.
32
8 Displaying output
In this last chapter, you’ll learn how to display the output of your programs in a nice
way. Since your program has a nice way of getting input (by means of the commands
seen on last chapter), it should also have a nice way of displaying output.
33
Number Area(s) frozen
1 Status area
2 Stack
3 Status area and stack
4 Menu
5 Menu and status area
6 Menu and stack
0 or 7 Whole display
34
A Answers to exercises
Chapter 2 — First concepts
1. (a) « 1 2 + »
(b) « « 1 2 + » EVAL »
(c) 3
(d) 3
(e) 1 and « 2 + »
(f) 3
2. « 3 ˆ π 4 3 * / →NUM »
3. « 32 - 5 * 9 / »
4. « 9 * 5 / 32 + »
7. « 4 ROLL * 3 ROLLD * - »
√
8. « ROT - SQ 3 ROLLD - SQ + »
√
9. « 3 PICK 4 * * NEG OVER SQ + SWAP NEG + SWAP 2 * /
»
√
10. The most obvious solution is « 3 PICK 4 * * NEG OVER SQ + SWAP
NEG ROT 2 * DUP 3 ROLLD / 3 ROLLD / DUP2 + 3 ROLLD NEG
+ » But Peter Karp sent two solutions that are shorter. Both work by changing
the well known Bhaskara’s formula into
s
2
−b −b c
x= ± −
2a 2a a
35
Chapter 3 — Local variables
1. « → a b u c d v
« ’a*d-b*c’ EVAL
’(d*u-b*v)’ EVAL OVER /
’(a*v-c*u)’ EVAL ROT /
»
»
Of course, you can use RPN notation if you prefer:
« →a b u c d v
« a d * b c * -
d u * b v * OVER /
a v * c u * ROT /
»
»
2. (a) « → a b c d e f g h i
’a(e*i-f*h)+b*(f*g-d*i)+c(d*h-e*g)’
»
(b) « → a b c d e f g h i
« a e i * f h * - *
b f g * d i * - * +
c d h * e g * - * +
»
»
3. « → a b c d e f g h i
« e i * f h * - *
b i * c h * - * NEG
b f * c e * - *
d i * f g * - * NEG
a i * c g * - *
a f * c d * - * NEG
d h * e g * - *
a h * b g * - * NEG
a e * b d * - *
9 →LIST
a e i * f h * - *
b f g * d i * - * +
c d h * e g * - * +
/ EVAL
»
»
36
Chapter 4 — Conditional tests
1. (a) 0
(b) 1
(c) 0
(d) 1
2. (a) 0
(b) 0
(c) 1
(d) 0
3. (a) 1
(b) 0
(c) 1
(d) 0
(e) 0
(f) 1
(g) 0
4. 0
6. 2.22222....
37
9. « → l m n
« IF l m > l n > OR THEN
IF m n < THEN
l m ’l’ STO ’m’ STO
ELSE
l n ’l’ STO ’n’ STO
END
END
IF m n > THEN
m n ’m’ STO ’n’ STO
END
l m n
»
»
10. « ROT 2 -
IF DUP 0 < THEN @ January or February?
12 + @ Correct month
SWAP 1 - SWAP @ Correct year
END
3 ROLLD
100 / DUP FP 100 * SWAP IP @ Split year
DUP 4 / IP SWAP 2 * - SWAP DUP 4 / IP
+ + + SWAP 2.6 * .2 - IP + 7 MOD @ Apply formula
→ dw
« CASE
dw 0 == THEN "Sunday" END
dw 1 == THEN "Monday" END
dw 2 == THEN "Tuesday" END
dw 3 == THEN "Wednesday" END
dw 4 == THEN "Thursday" END
dw 5 == THEN "Friday" END
dw 6 == THEN "Saturday" END
"Other day?!"
END
»
»
This program can be improved. First, we can make Saturday the default clause
because there will never be another day. But it can be improved even further,
without CASE. But that remove the purpose of the exercise. Anyway, you can
replace → dw « ...» with
{ "Sunday"
"Monday"
"Tuesday"
"Wednesday"
38
"Thursday"
"Friday"
"Saturday" }
SWAP 1 + GET
« 1 2 →n f i
« DO
’f’ i STO*
’i’ 1 STO+
UNTIL
i n >
END
f
»
»
4. « 0 @ Elapsed years
3E7 2E8 @ Initial populations
39
→ ny pa pb
« DO
’pa’ 1.03 STO*
’pb’ 1.015 STO*
’ny’ 1 STO+ @ Increase populations and number of years
UNTIL
pa pb ≥
pa "Pop. A" →TAG
pb "Pop. B" →TAG
ny "No. years" →TAG
»
»
5. « 0 @ Time elapsed
→m t
« WHILE
m .5 ≥
REPEAT
’m’ 2 STO/ @ Halve mass
’t’ 50 STO+ @ Increment time
END
@ Cute display for mass
m 1_g →UNIT "Mass" →TAG
t @ Let’s convert no. seconds to hours, minutes & seconds
3600 / IP "h " + @ Hours
t 3600 MOD DUP ’t’ STO @ Seconds - hours
60 / IP "mină" + + @ Minutes
t 60 MOD "s" + + @ Finally
»
»
40
You could also change it to calculate in reverse order, so that it isn’t neces-
sary to use -1 STEP.
(d) « 1
2 10 FOR i
i i SQ / @ Absolute value
-1 i ˆ * - @ Calculate sign and add
NEXT
»
(e) « 1000
2 50 FOR a
1000 a 1 - 3 * - a /
-1 k ˆ * -
NEXT
»
(f) « 48
1 10 FOR n
480 n 5 * - n 10 + /
-1 n ˆ * +
NEXT
»
1 2 3 14
7. (a) S = − + − ··· −
196 169 144 1
14
X (−1)a (−a)
S=
a=1
(15 − a)2
100 99 98 97 96 1
(b) S = + + + + + ··· +
1 1 2 6 24 99!
99
X 100 − b
S=
b!
b=0
61 59 57 1
(c) S = 63 + + + + ··· +
1! 2! 3! 30!
31
X 63 − 2i
S=
i=0
i!
1! 2! 3! 4! 5! 20!
(d) S = − + − + − ··· +
1 3 7 14 31 1048575
20
X (−1)j (−j!)
S=
j=1
2j − 1
8. « 1
3 105 FOR k
k 3 ˆ -1 k 2 / CEIL ˆ * INV -
2 STEP
32 * 3 XROOT
41
»
9. « 4 3 → d
« DO
4 d / -1 d 2 / CEIL ˆ * - 2 ’d’ STO+
UNTIL
DUP π →NUM - ABS .01 <
END
»
»
10. « 1 → x d
« 1 WHILE
DUP x EXP - ABS 1E-11 >
REPEAT
x d ˆ d ! / +
’d’ 1 STO+
END
»
»
42
√
13. « DUP DUP SWAP 2 / 3 ROLLD → y r
« DO
DUP SQ y + SWAP 2 * /
UNTIL
DUP r - ABS 1E-11 <
END
»
»
14. « ROT DUP DUP STEQ @ Save copy of equation in EQ
EQ→ - @ Split and subtract, to zero one side
DROP ROT DUP2 DUP PURGE ∂ @ Calculate derivate
→ f v d @ Save function, variable and derivate
« 1 30 START
DUP v STO f EVAL d EVAL / - @ Calculate approximation
NEXT
»
»
15. « 4 ROLL DUP DUP STEQ OBJ→ SWAP DROP
EQ→ -
DROP 4 ROLL DUP2 DUP PURGE ∂ → e f v d
« DO
DUP v STO
f EVAL DUP d EVAL / ROT SWAP -
UNTIL
SWAP ABS e <
END
»
»
43
SWAP NEG ROT 2 * DUP 3 ROLLD / 3 ROLLD / DUP2 +
3 ROLLD NEG +
2 →LIST
"SOLUTION"
{ "X’:" "X”:" }
{ } DUP
5 ROLL
IF INFORM THEN DROP END
END
»
3. « "SOLVE SYSTEM"
{ { "A:" "AX+BY=U" 0 1 9 13 }
{ "B:" "AX+BY=U" 0 1 9 13 }
{ "U:" "AX+BY=U" 0 1 9 13 }
{ "C:" "CX+DY=V" 0 1 9 13 }
{ "D:" "CX+DY=V" 0 1 9 13 }
{ "V:" "CX+DY=V" 0 1 9 13 } }
3 { } DUP
IF INFORM THEN
OBJ→ DROP
→a b u c d v
« ’a*d-b*c’ EVAL
’d*u-b*v’ EVAL OVER /
’a*v-c*u’ EVAL ROT /
»
END
»
4. « "INVERSE MATRIX" DUP
{ { "" "" 0 1 9 13 }
{ "" "" 0 1 9 13 }
{ "" "" 0 1 9 13 }
{ "" "" 0 1 9 13 }
{ "" "" 0 1 9 13 }
{ "" "" 0 1 9 13 }
{ "" "" 0 1 9 13 }
{ "" "" 0 1 9 13 }
{ "" "" 0 1 9 13 } } DUP 3 ROLLD
{ 3 1 } DUP 4 ROLLD
{ 0 0 0 0 0 0 0 0 0 } DUP DUP 6 ROLLD
IF INFORM THEN
OBJ→ DROP
→a b c d e f g h i
« e i * f h * - *
b i * c h * - * NEG
b f * c e * - *
44
d i * f g * - * NEG
a i * c g * - *
a f * c d * - * NEG
d h * e g * - *
a h * b g * - * NEG
a e * b d * - *
9 →LIST
a e i * f h * - *
b f g * d i * - * +
c d h * e g * - * +
/ EVAL
»
9 →LIST
IF INFORM THEN DROP END
END
»
45