02-16-2016, 03:41 AM
One of the features I like about later-model HP calculators is the use of named variables and the ability to solve for any one of the variables in an equation. The solver function available in the Advantage module is decent enough from a functional standpoint, but one generally needs to write multiple RPN functions for the same equation, depending on the variable being solved for. I came across this program which stores the values of all variables in registers and uses indirect register addressing to update the unknown variable during root finding. I extended this technique to make things more user-friendly. Here is the program I came up with:
The SLV program has two requirements: the Advantage module SOLVE function (or another root finder) and an RPN function that you write to evaluate your equation. To illustrate how the equation function is written, let's use a simple example from classical mechanics: x=v0*t+(1/2)*a*t^2. The RPN function for this equation is written in the following manner:
The function starts with a global label. Following that, a check of flag 05 is performed, which informs the function whether it's being called during root finding or for generating a user prompt. When evaluating the function during root finding, SLV clears flag 05, and the current estimate for the unknown variable is stored indirectly into the appropriate register in line 04. Lines 05-16 evaluate the function by recalling the values of the variables and performing the arithmetic. This is where you would enter the RPN steps for your equation f(x1,x2,...)=0. You can use up to 5 variables, and it's up to you to decide which variable goes into which register, 01-05. The alpha string following LBL 00 provides a user prompt and can be designed so that the variable name appears above the top-row key corresponding to the register (key "A" for 01, etc.). Here are the instructions for running the SLV program:
I like this technique because the equation and its prompting string are stored as a single function. While it takes a moment to plan out register usage, once you've created the function, you don't need to remember which register is which any more. I'd be pleased to hear any suggestions for improvement. It seems like something similar should have been written in the past, but I was unable to find anything. The AECROM has a nice interface for entering an equation and generating a program from it, but you have to decide ahead of time which variable you're going to solve for.
Code:
01◆LBL "SLV"
02 "FN NAME?"
03 AON
04 STOP
05 AOFF
06 ASTO 06
07◆LBL 01
08 SF 05
09 XEQ IND 06
10 AVIEW
11 STOP
12 GTO 01
13◆LBL A
14 STO 01
15 GTO 01
16◆LBL B
17 STO 02
18 GTO 01
19◆LBL C
20 STO 03
21 GTO 01
22◆LBL D
23 STO 04
24 GTO 01
25◆LBL E
26 STO 05
27 GTO 01
28◆LBL a
29 1
30 STO 00
31 GTO 00
32◆LBL b
33 2
34 STO 00
35 GTO 00
36◆LBL c
37 3
38 STO 00
39 GTO 00
40◆LBL d
41 4
42 STO 00
43 GTO 00
44◆LBL e
45 5
46 STO 00
47◆LBL 00
48 1
49 1 E-99
50 "INTERVAL?"
51 PROMPT
52 CLA
53 ARCL 06
54 CF 05
55 SOLVE
56 STOP
57 GTO 01
58 END
The SLV program has two requirements: the Advantage module SOLVE function (or another root finder) and an RPN function that you write to evaluate your equation. To illustrate how the equation function is written, let's use a simple example from classical mechanics: x=v0*t+(1/2)*a*t^2. The RPN function for this equation is written in the following manner:
Code:
01◆LBL "MOT"
02 FS? 05
03 GTO 00
04 STO IND 00
05 RCL 02 ' v0
06 RCL 03 ' t
07 *
08 RCL 04 ' a
09 RCL 03 ' t
10 X↑2
11 *
12 2
13 /
14 +
15 RCL 01 ' x
16 -
17 RTN
18◆LBL 00
19 " X V0 T A"
20 END
The function starts with a global label. Following that, a check of flag 05 is performed, which informs the function whether it's being called during root finding or for generating a user prompt. When evaluating the function during root finding, SLV clears flag 05, and the current estimate for the unknown variable is stored indirectly into the appropriate register in line 04. Lines 05-16 evaluate the function by recalling the values of the variables and performing the arithmetic. This is where you would enter the RPN steps for your equation f(x1,x2,...)=0. You can use up to 5 variables, and it's up to you to decide which variable goes into which register, 01-05. The alpha string following LBL 00 provides a user prompt and can be designed so that the variable name appears above the top-row key corresponding to the register (key "A" for 01, etc.). Here are the instructions for running the SLV program:
- Enter your equation as an RPN function as described previously.
- XEQ "SLV"
- Enter the name of your function (alpha is already on), followed by R/S.
- You will now have a list of variables above the top-row keys. If you forget the order, you can restore this prompt at any time by hitting R/S.
- Enter the values for n-1 variables by entering the value and then pressing the top-row key corresponding to that variable (or hit R/S first if you forgot which key).
- Press [SHIFT] followed by the top-row key corresponding to the variable you wish to solve for.
- (Optional) Enter the initial interval (a ENTER b) over which you wish to search for the value of the unknown variable, followed by R/S. If you press R/S without entering anything, the interval is set to (0, 1|.
- The value of the root is displayed if the solver was successful. At this point, you can press R/S to solve the equation again, for the same or a different variable.
I like this technique because the equation and its prompting string are stored as a single function. While it takes a moment to plan out register usage, once you've created the function, you don't need to remember which register is which any more. I'd be pleased to hear any suggestions for improvement. It seems like something similar should have been written in the past, but I was unable to find anything. The AECROM has a nice interface for entering an equation and generating a program from it, but you have to decide ahead of time which variable you're going to solve for.