LONG REALS MEET RESISTANCE by Joe Horn ========================== This should prove to you that you need the power of System RPL! Jason L Braddy (jlbraddy@IASTATE.EDU) asked for a program to calculate parallel resistance, and Joel Kolstad (kolstad@cae.wisc.edu) wrote: > This is what I just came up with on the spur of the moment: > \<<0 3 DEPTH START SWAP INV + NEXT INV \>> > Someone else might have something better if they thought about it a > little. Personally, I'd use a list of resistances and just > change the DEPTH to an OBJ->. Although mathematically flawless, there is a problem with this solution. All those INVs can easily accumulate roundoff error. For example, an input of 10 and 15 should yield 6, but instead it gives 5.99999999999. You might say that this is not enough of an error to worry about. But there's an easy way to guarantee perfect accuracy. If you only have two values to calculate, then the formula 1/(1/a+1/b) should not be used; instead, use ab/(a+b) which is more accurate because it has only a single division in it. A simple program for that is: %%HP:T(3); \<< * LASTARG + / \>> INPUT: Two reals. OUTPUT: real. EXAMPLE: 10 15 -> 6. If you have more than two resistors, the roundoff error can get really bad. My favorite examples violate the associative property of addition: if you enter 153, 238 and 252 into Joel's program, it gives one answer; enter them in reverse order, and you get another answer! And worst of all, both answers are wrong! This is not a unique case; there are infinitely many. And the more terms you have, the worse the error can get. One solution is to take the more accurate formula above and generalize it for any number of values. For example, for three values (a, b, c), we get abc/(ab+ac+bc); for four, we get abcd/(abc+abd+acd+bcd), and so on. A simple program for this method is: %%HP:T(3); \<< OBJ\-> OBJ\-> - 1 DUP ROT START 3 PICK * OVER + ROT ROT * SWAP NEXT / \>> INPUT: Array of reals. OUTPUT: real. EXAMPLE: [ 153 238 252 ] --> 68. But even this method occasionally gets roundoff errors due to the 12-digit limit of the HP 48. The solution, of course, is to use Long Reals during the calculation and only round the final result. PRES is a System RPL program to do that. It takes an array as its input, as suggested by Joel. It also uses the sign to assist problem solving. Like the financial software that uses the sign to differentiate between cash flow in and cash flow out, I'll use the sign here to differentiate between the resistance of an individual resistor and the total resistance of the circuit. INPUT: Array of Reals (positive = individual resistor, negative = total resistance) OUTPUT: Real (positive/negative = as above) System RPL listing produced by Brian Maguire's SRPL library: %%HP:; @ PRES by Joe Horn. Decode with SRPL-> ":: CK1&Dispatch # 4h :: %% 0 SWAP (37BCB) INDEX@ (3558E) %>%% %%1/ ROT %%+ SWAP LOOP DROP %%1/ %%>% %CHS ; ;" Note: The (37BCB) and (3558E) above are in-line five-nibble addresses (unsupported and unnamed entry points); this is how Maguire's library decompiles them. They are NOT comments. If using Detlef Mueller's RPL.LIB to compile it, change (37BCB) to PTR 37BCB, etc. EXAMPLE 1: What is the total resistance of a circuit of three resistors in parallel, with individual values of 120, 144, and 180 ohms? SOLUTION: Type [ 120 144 180 ] and press PRES. See -48; the circuit has a total resistance of 48 ohms. EXAMPLE 2: If you have two resistors in parallel, each 120 ohms, and you want to add a third one in parallel with them such that the total resistance becomes 44 ohms, what value resistor must you use? SOLUTION: Type [ 120 120 -44 ] and press PRES. See 165; the third resistor must have a value of 165 ohms. EXAMPLE 3: Bill can paint a house in 6 hours; Ted can do it in 10 hours. When they work together with Alice, they finish in 3 hours. How long would it take Alice by herself? SOLUTION: Type [ 6 10 -3 ] and press PRES. See 15; it would take Alice 15 hours to paint the house by herself. -Joseph K. Horn- EQU akcs.joehorn@hpcvbbs.cv.hp.com