(48G) GCD: Greatest Common Divisor - Printable Version +- HP Forums (https://www.hpmuseum.org/forum) +-- Forum: HP Software Libraries (/forum-10.html) +--- Forum: General Software Library (/forum-13.html) +--- Thread: (48G) GCD: Greatest Common Divisor (/thread-11296.html) Pages: 1 2 |
(48G) GCD: Greatest Common Divisor - Thomas Klemm - 08-30-2018 03:21 PM This solution is from: HP 48 Insights Programs Contains all the example programs from the book HP 48 Insights Part 1, by Bill Wickes. INSIGHTS/PROGRAMS/GCD: Code: %%HP: T(3)A(D)F(.); However we can make it a bit shorter: Code: « Example: 54 24 GCD 6 RE: (48G) GCD: Greatest Common Divisor - Werner - 08-31-2018 08:34 AM Ow that's an old one. This is still quite a bit shorter: Code: \<< Cheers, Werner RE: (48G) GCD: Greatest Common Divisor - Albert Chan - 08-31-2018 12:12 PM Hi, Werner: I like your shorter version ! But, it is slightly different than Thomas Klemm code. Instead of confirming nonzero x before y % x, it test for y instead. (Bill Wickes version also assumed start with nonzero x) RE: (48G) GCD: Greatest Common Divisor - Werner - 08-31-2018 01:18 PM Since GCD(x,y) = GCD(y,x) that makes no difference. And when does it throw an error? GCD(x,0) = GCD(0,x) = x, even for x=0 Cheers, Werner RE: (48G) GCD: Greatest Common Divisor - Albert Chan - 08-31-2018 02:06 PM (08-31-2018 01:18 PM)Werner Wrote: Since GCD(x,y) = GCD(y,x) that makes no difference. If entered: 0 54 GCD, the code returned gcd of 54, as expected. If entered: 54 0 GCD, stack = {0 54} SWAP DUP2, stack = {54 0 54 0} Inside REPEAT, stack = {0 54 0} MOD, will do an illegal operation 54 % 0, thus ERROR BTW, I don't know what MOD will do for 54 % 0, ERROR was my guess. If the calculator returned x % 0 as x, then ignore my post. All is well ... RE: (48G) GCD: Greatest Common Divisor - rprosperi - 08-31-2018 02:29 PM (08-31-2018 02:06 PM)Albert Chan Wrote: BTW, I don't know what MOD will do for 54 % 0, ERROR was my guess. The program works fine for both 0 54 GCD or 54 0 GCD, returning 54 in both cases. Friendly suggestion: Get an actual calculator (or install an emulator) and play along with the rest of us. It's the best way to learn RPL (or RPN, etc.) RE: (48G) GCD: Greatest Common Divisor - Albert Chan - 08-31-2018 03:46 PM (08-31-2018 02:29 PM)rprosperi Wrote:(08-31-2018 02:06 PM)Albert Chan Wrote: BTW, I don't know what MOD will do for 54 % 0, ERROR was my guess. You mean it work for *all* 3 programs ? Klemm version work. I was referring to the other two ... I just downloaded Hp50g emulator: 54 0 MOD return ?, not 54 RE: (48G) GCD: Greatest Common Divisor - rprosperi - 08-31-2018 10:08 PM (08-31-2018 03:46 PM)Albert Chan Wrote: You mean it work for *all* 3 programs ? No, sorry I was not clear, I was referring to Werner's program; I thought that was the one you were referencing. Great, glad you're jumping-in with 50g Emulator! Soon you'll want a real 50g, then maybe a 48GX, etc. Careful, it can be addictive... RE: (48G) GCD: Greatest Common Divisor - Albert Chan - 08-31-2018 11:40 PM (08-31-2018 10:08 PM)rprosperi Wrote:(08-31-2018 03:46 PM)Albert Chan Wrote: You mean it work for *all* 3 programs ? Turns out, we are both right (with Werner's program): With approx mode: 54 0 GCD returns 54 (calculator assumed 54 % 0 = 54) Under exact mode: 54 0 GCD returns '?' (technically, 54 % 0 is undefined) In fact, Werner's code will not work in exact mode at all, except for initial Y = 0. It always return '?', because X always reduced to zero, causing undefined Y % X. Hp50g emulator is fun RE: (48G) GCD: Greatest Common Divisor - rprosperi - 09-01-2018 02:52 AM (08-31-2018 11:40 PM)Albert Chan Wrote: Turns out, we are both right (with Werner's program): Regardless of the mode the 50g is set to (Exact or Approximate), it interprets numbers as approximate or exact based on the format of the number provided. Approximate numbers always must include a decimal point, and Exact numbers never include a decimal point. So even in Exact Mode, entering 54. 0. GCD will treat the parameters as approximate. In my case I was actually testing with a 48GX; there is no distinction of type here, all numbers are approximate, even if entered as "54 0 GCD". I agree the 50g emulator is great, but an actual device is even more satisfying (although not as fast for extended computations). RE: (48G) GCD: Greatest Common Divisor - Werner - 09-01-2018 04:14 PM Hello Albert, you're absolutely right. I wrote this when the most advanced HP was the 48GX, and so I never realized it didn't work for decimal integers. Still, I can get it shorter: Code: \<< CHeers, Werner RE: (48G) GCD: Greatest Common Divisor - Thomas Klemm - 09-01-2018 05:05 PM (09-01-2018 04:14 PM)Werner Wrote: Still, I can get it shorter: Can somebody explain how the size of these programs are determined? It puzzles me a bit that this program uses 22.5 bytes: Code: « WHILE REPEAT END » Whereas this longer program uses only 20 bytes: Code: « WHILE REPEAT SWAP END » Thanks in advance Thomas RE: (48G) GCD: Greatest Common Divisor - Albert Chan - 09-01-2018 05:57 PM Hi, Thomas Klemm My guess is « WHILE REPEAT END » cannot compile, and had to store internally as « WHILE REPEAT *PASS* END ». *PASS* is just a placeholder. Above thus similar to Python code, while 1: pass To minimize program byte count, common keywords use less storage. *PASS* probably is pretty rare for a (internal) keyword, which does nothing ... RE: (48G) GCD: Greatest Common Divisor - Thomas Klemm - 09-01-2018 06:22 PM (09-01-2018 05:57 PM)Albert Chan Wrote: My guess is « WHILE REPEAT END » cannot compile Nah, that's a valid program. You can even run it. It just pops the elements of the stack until it reaches 0. RE: (48G) GCD: Greatest Common Divisor - DavidM - 09-01-2018 06:46 PM (09-01-2018 05:05 PM)Thomas Klemm Wrote: Can somebody explain how the size of these programs are determined? The reason this is larger is due to the way that the internal UserRPL compiler adds an empty "secondary" in between the REPEAT and the END. The empty secondary is comprised of the two SysRPL primitives :: and ;. Each one uses 2.5 bytes, for a total of 5 bytes which are "invisible" in the text form of the source code. Something has to exist after the REPEAT and before the END for the RPL stream to be processed correctly. (09-01-2018 05:05 PM)Thomas Klemm Wrote: Whereas this longer program uses only 20 bytes: This one is compiled as you would probably expect, with the SWAP command between the REPEAT and END. SWAP only takes 2.5 bytes (compared to the 5 above), hence the smaller size of the total program. For completeness, here's the SysRPL representations of both programs after the RPL compiler is done with them: Code:
RE: (48G) GCD: Greatest Common Divisor - Thomas Klemm - 09-01-2018 07:12 PM Interesting. But still I don't understand why my program in post #1 uses 35 bytes while Werner's program in post #11 uses only uses 32.5 bytes. My program is shorter if we count the commands. Is there another :: ; included somewhere? Cheers Thomas RE: (48G) GCD: Greatest Common Divisor - DavidM - 09-01-2018 07:31 PM (09-01-2018 07:12 PM)Thomas Klemm Wrote: Is there another :: ; included somewhere? Short answer: Yes. Longer answer: The savings in Werner's version comes because, in this case, there's only one command in between the REPEAT and END steps. In the RPL stream, the next item after the REPEAT has to be skippable, so if there's more than one command they all have to be encapsulated in a secondary so as to be a single entity. Here's the compiled versions of both programs: Code: :: RE: (48G) GCD: Greatest Common Divisor - Thomas Klemm - 09-01-2018 07:40 PM Thanks again for taking the time for this analysis! Just out of curiosity: what would be the shortest SysRPL program to calculate the GCD of two numbers? Cheers Thomas RE: (48G) GCD: Greatest Common Divisor - DavidM - 09-01-2018 08:41 PM (09-01-2018 07:40 PM)Thomas Klemm Wrote: Thanks again for taking the time for this analysis! Everyone's least favorite answer: "It depends..." If the program is intended to behave in a "normal" fashion (accepting varying argument types, preserving stack for UNDO/LAST, etc.), I'm not sure you could save any space at all by going the SysRPL route. If you don't care about error trapping or argument type checking (which leaves you exposed for a nasty crash if you forget which types of arguments to use), you could go with a "throw caution to the wind" approach and do something like this: Code: :: This only works with approximate numbers, and weighs in at 25 bytes. Not much savings for the risk and hassle, IMHO. Then of course you'd need something else entirely if exact integers were involved, which makes going the SysRPL route even less attractive. I'd stick with a UserRPL version for something like this. RE: (48G) GCD: Greatest Common Divisor - rprosperi - 09-01-2018 09:57 PM (09-01-2018 07:40 PM)Thomas Klemm Wrote: Just out of curiosity: what would be the shortest SysRPL program to calculate the GCD of two numbers? Isn't this shorter? Code: :: SCNR |