How do I learn RPL and solve this problem with it? - Printable Version +- HP Forums (https://www.hpmuseum.org/forum) +-- Forum: HP Calculators (and very old HP Computers) (/forum-3.html) +--- Forum: General Forum (/forum-4.html) +--- Thread: How do I learn RPL and solve this problem with it? (/thread-9150.html) Pages: 1 2 RE: How do I learn RPL and solve this problem with it? - emece67 - 09-25-2017 08:04 PM I have not read the whole thread, but I'm wondering if the fact that the base resistor values form a, more or less, geometric series is used in some way. Thus, the E12 series uses 12 values on each decade, this way the ratio between one value and the next is $$\sqrt[12]{10}=1.2115\ldots$$. This way the E12 values are: 1 $$\sqrt[12]{10}=1.2115\ldots\approx1.2$$ $$(\sqrt[12]{10})^2=1.4677\ldots\approx1.5$$ $$(\sqrt[12]{10})^3=1.7782\ldots\approx1.8$$ $$(\sqrt[12]{10})^4=2.1544\ldots\approx2.2$$ $$(\sqrt[12]{10})^5=2.6101\ldots\approx2.6$$ (E24 value is 2.7) $$(\sqrt[12]{10})^6=3.1622\ldots\approx3.2$$ (E24 value is 3.3) $$(\sqrt[12]{10})^7=3.8311\ldots\approx3.8$$ (E24 value is 3.9) $$(\sqrt[12]{10})^8=4.6415\ldots\approx4.6$$ (E24 value is 4.7) $$(\sqrt[12]{10})^9=5.6234\ldots\approx5.6$$ $$(\sqrt[12]{10})^{10}=6.8129\ldots\approx6.8$$ $$(\sqrt[12]{10})^{11}=8.2540\ldots\approx8.3$$ (E24 value is 8.2) I'm not yet worked this, but perhaps it would be possible to only search for resistor pairs that are zero steps apart, then one, then two,... and so on. Regards. RE: How do I learn RPL and solve this problem with it? - David Hayden - 09-25-2017 08:17 PM What a fantastic problem!!! For UserRPL programming, download HPUserEdit 6 from hpcalc.org. Also download the file that converts the menus etc into English since the original is in... Spanish? HPUserEdit will let you write and debug your programs on the PC. If your 50g came with the 184 page "User's Manual" then you should lock that book securely in a safe for now. It's more like a quick reference quide and will only serve to confuse you as a beginner. Use the "User's Guide" instead. It has much more detail. The biggest problem with the User's Guide has to do with the 4 major modes of operation of the 50g: RPN vs. Algebraic input, and Soft Menus vs. choose boxes. Because of these modes, the User's Guide is full of things that say: Now to do XYZ in RPN mode, enter these keys (half-page examples follows). If you're using algebraic mode, do this (another half page example follows). The above assume that you're using choose boxes. If you have soft menus, your screens will look like this... and this... For this reason, you might want to consider using the 48GX User's Guide instead. It's all RPN and all soft menus. RE: How do I learn RPL and solve this problem with it? - Claudio L. - 09-25-2017 08:27 PM (09-25-2017 06:36 PM)mfleming Wrote:  Hi guys, I believe you've been misled by the OP's approach of pre-computing all possible values of two resistors in parallel (combinatorial explosion), when in reality there are only a few combinations of two resistors that will meet the original criteria of being within 1% of the desired resistance value. I agree, there's 4 or 5 valid values, no need to precompute anything. The basic tasks can be broken into: Find the smallest resistor in E12 that is >= requested. Find the largest resistor in E12 <= 2*requested. Make a list of all valid resistors in E12 between them (only 4 or 5 total, since 1.211^4 > 2) Compute the second resistor needed for each case, but in each case finding the closest E12 resistor to the computed value. Compute the error for each case, make sure is within tolerance. Present the choice to the user in a nice way Note that 1, 2 and 4 are basically the same, lookup the E12 resistor given a value, but in one case get the lower bound, in the other the upper and the third is closest match. Perhaps a single routine can handle all 3 cases. Task #3 can also reuse the same routine, since the next valid resistor would be the closest match to R*1.211 (with R being a valid E12 resistor). That's the simplest way I see it. And that's not taking anybody by the hand, as each task is a project on itself. So the first goal would be a routine that given any value, finds the lower, upper and closest match in the E12 series. RE: How do I learn RPL and solve this problem with it? - brickviking - 09-26-2017 01:02 AM I'm no good at the mathematics behind all this, I've been a bit lost. However, I realised that there's also a real-world value of each resistor, not just a theoretic L T and ≤ 2T: Pick the first/next value for R1 from the E12 series Calculate the value of R2, which is the resistor parallel to R1 that yields a total resistance of T Take the two closest resistors R2a and R2b and determine the total resistance R1||R2a and R1||R2b Or simply consider only the resistor R2c that is closest to R2. If the tolerance is not yet met, repeat with next R1 Else display R1 and R2a or R2b and quit Instead of quitting as soon as a combination within the allowed tolerance is found you can also run through all possible R1 (i.e. all resistors > T and ≤ 2T) and return the combination with the overall lowest deviation. But due to the individual tolerances of the two resistors this may not make much sense. On the other hand this returns the best possible combination even if it is not within tolerance. Here is an example: Try to find a combination for a target resistance of T = 350 Ω The first larger R1 in the E12 series is 390 Ω R2 = 350*390 / (390–350) = 3412,5 Ω So R2a = 3300 Ω and R2b = 3900 Ω 390*3300 / (390+3300) = 348,78 Ω which is T – 0,35% 390*3900 / (390+3900) = 354,55 Ω which is T + 1,30% The first value (3300 Ω) is within tolerance, so we already got a solution. Otherwise repeat these steps with R1 = 470, 560 and 680 Ω. Higher R1 values are not required, as 820 Ω already is > 2*350 Ω. This way a combination of two parallel resistors can be found. Here the best result was 348,78 Ω. In a final step, the gap to 350 Ω can be closed with another 1,2 Ω resistor in series. But since we are already within the tolerance of the individual resistors this is not really required. What do you think? Dieter RE: How do I learn RPL and solve this problem with it? - Claudio L. - 09-26-2017 06:37 PM (09-26-2017 02:55 PM)pier4r Wrote:  I meant: the list of resistors (that are 96) is good to have in a precomputed form. Here's an idea for you: just have a list of the 12 basic ones, counting from 1.0, 1.2,1.5... You can always split a number with MANT and XPON. Since MANT gives you the mantissa 1.0 < x < 10.0 it works perfect. All we need to add is a 10 at the end of the list, and we are guaranteed the mantissa falls within the list. Then at the end we can multiply back by the XPON and there you go, or you can multiply the list by the XPON first, and work with the whole number, your choice. EDIT: Just to clarify, not to multiply directly by the XPON, but by the ALOG of the XPON. RE: How do I learn RPL and solve this problem with it? - Didier Lachieze - 09-26-2017 06:46 PM Here's a program for the HP Prime using some ideas from Claudio to speed it up (for me PPL is much easier than RPL for writing quick programs such as this one) : Code: Suffix(n) BEGIN  CASE   IF 3≤LOG(n)<6 THEN n:=STRING(n/1ᴇ3)+"K" END;   IF 6≤LOG(n)<9 THEN n:=STRING(n/1ᴇ6)+"M" END;   DEFAULT n  END; END; EXPORT RES(R) BEGIN LOCAL val:={10,12,15,18,22,27,33,39,47,56,68,82}; LOCAL rng:={.1,1,1ᴇ1,1ᴇ2,1ᴇ3,1ᴇ4,1ᴇ5,1ᴇ6}; LOCAL res:={}; LOCAL a,b,j,k,r0,r1,r2,rp; FOR j FROM 1 TO 8 DO  res:=CONCAT(res,val*rng(j)); END; FOR j FROM 1 TO SIZE(res) DO   a:=res(j);   IF a>2*R THEN BREAK; END;   IF a≥R THEN     FOR k FROM j TO SIZE(res) DO       b:=res(k);       rp:=a*b/(a+b);       IF ABS(R-rp) 1 1 => 1,2 2 => 1,5 3 => 1,8 ... 10 => 6,8 11 => 8,2 12 => 10 13 => 12 14 => 15 ... 53 => 27000 54 => 33000 ... Dieter Edited to correct an error in the program code RE: How do I learn RPL and solve this problem with it? - Claudio L. - 09-26-2017 08:22 PM (09-26-2017 06:57 PM)pier4r Wrote:  First: thanks for sharing. Second: for practical purposes (optimization comes after correct resolution) is it important? I mean if the list would be 200 or 2000 elements, I would find your tip needed due to memory constraints, but 96 elements are not that much even for userRPL I'd say (if they are precomputed). Or do I miss something? Nope, not missing anything. Just that I didn't see that as an optimization, my head sees it more as: argument reduction / algorithm / output. And my suggestion was in the argument reduction category, so I suggested it first, that's all. RE: How do I learn RPL and solve this problem with it? - Claudio L. - 09-26-2017 08:25 PM (09-26-2017 07:01 PM)Dieter Wrote:  Unfortunately the actual resistor values are sometimes rounded up, sometimes down. But there is a way to calculate the nominal values of the E12 series. Here is a code snippet in VBA: Code: Function R(i) a = i Mod 12 + 1 If a < 8 Then w = 0.83 * 1.22 ^ a Else w = 0.88 * 1.204 ^ a b = Round(b, 1) R = 10 ^ (i \ 12) * w End Function b=Round(b,1) doesn't seem right, as b is undefined? RE: How do I learn RPL and solve this problem with it? - Dieter - 09-26-2017 08:36 PM (09-26-2017 08:25 PM)Claudio L. Wrote:  b=Round(b,1) doesn't seem right, as b is undefined? Oops, sorry, this "b" is supposed to be a "w". I will correct the original post. Dieter RE: How do I learn RPL and solve this problem with it? - pier4r - 09-26-2017 10:20 PM So still a greedy algorithm but a bit better than "compute all" Quite quick on the 50g. Code:  \<<     @3167      "resistorToApprox" DROP               { 10 12 15 18 22 27 33 39 47 56 68 82 }  "baseResistors" DROP     { 1. 1.2 1.5 1.8 2.2 2.7 3.3 3.9 4.7  5.6 6.8 8.2 10. 12. 15. 18. 22.  27. 33. 39. 47. 56. 68. 82. 100.  120. 150. 180. 220. 270. 330. 390.  470. 560. 680. 820. 1000. 1200. 1500.  1800. 2200. 2700. 3300. 3900. 4700.  5600. 6800. 8200. 10000. 12000. 15000.  18000. 22000. 27000. 33000. 39000. 47000.  56000. 68000. 82000. 100000. 120000. 150000.  180000. 220000. 270000. 330000. 390000.  470000. 560000. 680000. 820000. 1000000. 1200000.  1500000. 1800000. 2200000. 2700000. 3300000. 3900000.  4700000. 5600000. 6800000. 8200000. 10000000. 12000000.  15000000. 18000000. 22000000. 27000000. 33000000. 39000000.  47000000. 56000000. 68000000. 82000000. } "allResistors" DROP     DUP SIZE "allResistorsNumber" DROP     { 0.1 10 100 1000 10000 100000 1000000 } "resistorRanges" DROP     {} "resultSerial" DROP     {} "resultParallel" DROP     0 "value1" DROP     0 "value2" DROP     {} "allResistorsListTemp" DROP     {} "allResistorsListTemp2" DROP     0 "inputValueTmp" DROP          \->     @input     resistorToApprox          @localVar     baseResistors     allResistors     allResistorsNumber     resistorRanges     resultSerial     resultParallel     value1     value2     allResistorsListTemp     allResistorsListTemp2     inputValueTmp          \<<       \<<         @first we build the list of all possible resistors from the base one.              @for every element in the range of resistors we expand the list of available         @resistors         1 resistorRanges SIZE         FOR position           'allResistors'           baseResistors           resistorRanges position GET           *           STO+         NEXT                  @now we order the resistors, although it is not strictly needed for the result         allResistors :2:LSORT EVAL 'allResistors' STO               @we can also save the result as precomputed list       \>>        DROP         @not needed, we have the list precomputed now.            @here we have all the resistors needed.              @####       @serial              IF         resistorToApprox 2 >           @only in this case serial can be done           @otherwise the value is too little.       THEN         1 2         START           allResistors           resistorToApprox value1 - allResistorsNumber LNDUP           \<=             @after this operation we have on the stack a list             @that reports all positions less than the input value.           1 MPOS 1 LROT HEAD             @we have the position of the largest element in the list             @smaller than the value             @(would be nice if the list of davidM             @would include even those little commands so one has not to think about them)           allResistors SWAP GET 'value1' STO                       'resultSerial' value1 STO+         NEXT                  @output         resultSerial @resistors         resultSerial LSUM @value         DUP resistorToApprox SWAP %T @percentage         100 SWAP - @percentage difference         2 RND       END              @####       @parallel              "parallel"              0 'value1' STO       1 2       START         allResistors INV         resistorToApprox INV value1 - allResistorsNumber LNDUP         \<=           @after this operation we have on the stack a list           @that reports all positions less than the input value.           @now since we have the invese the larger elements are smaller           @so what we need is the first element smaller         1 POS           @we have the position of the largest element in the list           @smaller than the value         allResistors SWAP GET 'value1' STO                   'resultParallel' value1 STO+         value1 INV 'value1' STO       NEXT              @output       resultParallel @resistors       resultParallel INV LSUM INV 2 RND @value       DUP resistorToApprox SWAP %T @percentage       100 SWAP - @percentage difference       2 RND     \>>   \>>` note that serial will return positive percentage difference, parallel negative ones (because the inverted value is always bigger than the given one). Since it is greedy, I found at least some counterexample to the question "does it found always the best solution?" for example with 28, the serial solution is ok the parallel one is off. Anyway I learned that better to proceed by increasing improvements rather than being stuck.