(50G) Digits sum (50g) - Printable Version +- HP Forums (https://www.hpmuseum.org/forum) +-- Forum: HP Software Libraries (/forum-10.html) +--- Forum: General Software Library (/forum-13.html) +--- Thread: (50G) Digits sum (50g) (/thread-14839.html) (50G) Digits sum (50g) - Juan14 - 04-12-2020 08:05 PM The program below finds the sum of the digits of an integer, for example for 236067 the program returns 2+3+6+0+6+7 = 24. « 0 SWAP WHILE DUP REPEAT 10 IDIV2 ROT + SWAP END DROP » If you change the number 10 next the command IDIV2 to 8, you will get the sum of digits of the number in base 8, for example 236067 will return 20 and 236067 in base 8 is 751043, the sum of the digits is 20. Returning to base 10, you apply the program again and again until you get to single digit number. For example applying successively the program to 7897869769, we get 76, 13 and 4. I was trying factorials and notice that after 6!, if you reduce to a single digit, this is always 9. I know there are guys out there with better knowledge that can explain this. RE: Digits sum (50g) - grsbanks - 04-13-2020 09:45 AM (04-12-2020 08:05 PM)Juan14 Wrote:  I was trying factorials and notice that after 6!, if you reduce to a single digit, this is always 9. I know there are guys out there with better knowledge that can explain this. 6! = 1 x 2 x 3 x 4 x 5 x 6 = 1 x 2 x 3 x 4 x 5 x 2 x 3 3 is a factor of 6! twice, which means that it's a multiple of 9, as is the factorial of any integer above 6. The phenomenon you describe is a property of all multiples of 9. RE: Digits sum (50g) - Nihotte(lma) - 04-13-2020 08:38 PM (04-12-2020 08:05 PM)Juan14 Wrote:  The program below finds the sum of the digits of an integer, for example for 236067 the program returns 2+3+6+0+6+7 = 24. « 0 SWAP WHILE DUP REPEAT 10 IDIV2 ROT + SWAP END DROP » That's a pretty loop Otherwise, no loop (lol) ! So, Juan14, I propose you this one !? (HP48 : no IDIV2 available) SUMAD #F010h 97.5 « 10 → n b « n b MOD IF n b ≥ THEN n b / IP SUMAD + END » » RE: Digits sum (50g) - Juan14 - 04-13-2020 11:01 PM Thank you grsbanks and Nihotte(Ima) for your replays. The recursive program is very interesting, the 50g can handle huge integer numbers and a recursive program would take a lot of resources. RE: Digits sum (50g) - DavidM - 04-15-2020 03:49 AM That's an interesting program to experiment with, Juan! Same answer for base 10, but a completely different method: Code: ```\<<    R\->I \->STR    0 SWAP    WHILE       DUP SIZE    REPEAT       DUP TAIL SWAP HEAD       NUM 48. -       ROT +       SWAP    END    DROP    R\->I \>>``` IDIV2 is very slow, and I usually go out of my way to avoid using it for anything repetitive (which ironically is where it would be most useful). A 2000-digit number passed to your original program takes about 240 seconds to complete on my 50g. That same number passed to the above program finished in about 32 seconds. The ListExt library contains a couple commands (I→NL, LSUM) which make all of this much easier. In particular, I→NL creates a list whose elements are the individual digits of the original number. LSUM is a more forgiving version of ΣLIST (it also accepts lists with 0 or 1 element): Code: ```\<<    I\->NL    LSUM    R\->I \>>``` It's even faster than the original program above -- a 2000-digit number is summed in about 3 seconds with this code. RE: Digits sum (50g) - John Keith - 04-15-2020 10:21 PM I was going to post about I->NL but you beat me to it. Also I->BL for bases other than 10. For integers up to 100 digits or so, I->NL LSUM is fastest. For numbers larger than 100 digits, this strange program is actually faster: Code: ``` \<<   \->STR 0 SWAP 1. 9.     FOR j j 48. + CHR "" SREPL j * ROT + SWAP     NEXT DROP \>>``` SREPL is crazy fast, I have used it for lots of odd purposes like this. Here is a similar program that returns a list of 10 numbers which are the counts of each digit from 1 to 9 in a large integer: Code: ``` \<<     \->STR 48. 57.     FOR j j CHR "" SREPL SWAP     NEXT DROP 10. \->LIST \>>``` For integers less than 70 digits or so, I\->NL LSORT LRPCT is faster (and a lot shorter). RE: Digits sum (50g) - DavidM - 04-17-2020 04:31 AM (04-15-2020 10:21 PM)John Keith Wrote:  ...For numbers larger than 100 digits, this strange program is actually faster: Code: ``` \<<   \->STR 0 SWAP 1. 9.     FOR j j 48. + CHR "" SREPL j * ROT + SWAP     NEXT DROP \>>``` SREPL is crazy fast, I have used it for lots of odd purposes like this. This is a great example of the power of SREPL. I never would have thought of using it for that purpose, but it works quite well as you have indicated. The others are similarly well-suited for the tasks you identified. SREPL is almost entirely written in Saturn code, and it makes repeated use of MOVE instructions which execute at native ARM speed. So it really is a speed demon. Thanks to Juan, grsbanks, Nihotte(lma), and John Keith for all the thought-provoking concepts! RE: Digits sum (50g) - Gerald H - 04-17-2020 10:42 AM Very nice & fast programme, John Keith. So fast that a sys version is not really necessary, but I couldn't resist: Code: ```Size: 69.5 CkSum: # 2F18h ::   CK1&Dispatch   # FF   ::     FPTR2 ^Z>S     ZEROSWAP     BINT10     ONE_DO     INDEX@     BINT48     #+     #>CHR     CHR>\$     NULL\$     FPTR F 1A     COERCE     INDEX@     #*     ROT#+     SWAPLOOP     DROP     UNCOERCE   ; ;``` RE: (50G) Digits sum (50g) - gor1060 - 12-11-2022 11:15 AM My asm-version of programm: " :: CODE C=DAT1 A ?C#0 A GOYES INTGR? LA 00201 *ERROR GOVLNG =Errjmp *INTGR? CD1EX A=DAT1 A D1=C R1=C A LC 02614 ?A=C A GOYES MAIN LA 00202 GOTO ERROR *MAIN SAVE C=R1 A D1=C C=DAT1 A D1=C D1=D1+5 A=DAT1 A LC 00006 ?A=C A GOYES ZERO A=A-5 A A=A-1 A A=A-1 A B=0 W C=0 W D1=D1+4 *Loop D1=D1+1 C=DAT1 1 B=B+C W A=A-1 A GONC Loop A=B W GOTO Skip *ZERO A=0 W *Skip GOSBVL HXDCW GOSBVL FLOAT SETHEX GOVLNG PUSH%LOOP ENDCODE SWAPDROP FPTR2 ^R>Z ; @"