AH! Ces sites de programmeurs petits et jeunes ! Du C+#?+, JAVA, PHP, Python,... mais pas de RPN ou RPL je vais leur écrire pour rajouter un onglet :Danny a écrit : ↑19 juin 2020 23:46[..]Un peu de lecture pour les curieux : https://www.geeksforgeeks.org/finding-s ... gle-digit/[..]
Code : Tout sélectionner
01 LBL "DIGSUM
02 9 MOD x=0? LASTx
06 ENDExcellent, il s'agit typiquement qu'une récurrence de queue. La preuve absolue sont les deux dernières lignes 1030 GOSUB 1000 et 1040 RETURN qui devient en fait 1030 GOTO 1000 et cela marche même sur mon pauvre SHARP PC-1211 qui peut suivre cet algorithme en utilisant qu'un seul des ses quatre niveaux d'appels des sous-routines.badaze a écrit : ↑20 juin 2020 01:12[..]
Exemple avec le calcul de factorielles. Bon il n’y a pas de variables locales mais on peut s’en passer.Code : Tout sélectionner
10 INPUT "A=",A 20 B = 1 30 GOSUB 1000 40 PRINT "......";B; 50 END 999 REM *** FACTORIELLE 1000 IF A = 0 THEN RETURN 1010 B = B * A 1020 A = A - 1 1030 GOSUB 1000 1040 RETURN
Sur SHARP PC-1211 le code suivant ne fonctionne que jusqu'à la factorielle 4 à cause de la limite du nombre d'appels GOSUB emboités:
Code : Tout sélectionner
1:"F" AREAD N:F=1:GOSUB 5:PRINT F:END
5:IF N LET F=F*N,N=N-1:GOSUB 5
6:RETURN
Code : Tout sélectionner
1:"F" AREAD N:F=1:GOSUB 5:PRINT F:END
5:IF N LET F=F*N,N=N-1:GOTO 5
6:RETURNCe qui fait , que je m'empresse d'en simplifier la structure. Rien ne sert d'utiliser un GOSUB pour un seul appel !
Code : Tout sélectionner
1:"F" AREAD N:F=1
5:IF N LET F=F*N,N=N-1:GOTO 5
6:PRINT F:ENDCode : Tout sélectionner
1:"F" AREAD N:F=1
5:IF N FOR I=1 TO N:F=F*I:NEXT I
6:PRINT F:ENDL'algorithme déployé qui consiste à transformer la définition récursive de la fonction factorielle en une récursivité de queue à l'aide de deux variables (non nécessairement locales) a justement fait l'objet d'une vidéo (en anglais) Computerphile issue du département Computer Science at the University of Nottingham.
L'idée maitresse est d'utiliser une des variables comme un compteur et l'autre comme un accumulateur. L'exemple avec les nombres de Fibonacci montre qu'il faut parfois plus de variables pour transmettre plus d'arguments.
Illustré en RPL, l'idée pour la factorielle est de faire :
Code : Tout sélectionner
rFACT: « 1 goFACT »
goFACT: « IF OVER THEN OVER * OVER SIGN NEG ROT + SWAP goFACT END »c'est à dire en utilisant un RPL plus proche des langages algébriques:
Code : Tout sélectionner
'rFACT=goFACT(n,1)' DEF
'goFACT(n,f)=IFTE( n==0 , f , goFACT(n-SIGN(n),n*f) )' DEF
Code : Tout sélectionner
rSDC: « IF DUP 9 > THEN 0 goSDC END »
goSDC: « IF OVER THEN SWAP 10 DUP2 / IP 4 ROLLD MOD + goSDC ELSE rSDC END »
Code : Tout sélectionner
'rSDC(n)=IFTE( n>9 , goSDC(n,0) , n )' DEF
'goSDC(n,s)=IFTE( n>0 , goSDC(IP(n/10),s+(n MOD 10)) , rSDC(s) ) DEFCode : Tout sélectionner
SDC: « DUP 9 MOD DUP 9 IFTE OVER IFTE »Code : Tout sélectionner
SDC: « 9 MOD DUP 9 IFTE »ce qui doit bien les 14 ou 16 octets donc parle Bernouilli92.
Comme nous sommes dans un MPO, je m'empresse de donner pour TI-57 LCD un code bien plus court (mais ce code doit être immédiatement adaptable à une vraie TI-57 à leds):
Code : Tout sélectionner
-- St
56 00 C.t // Met à zéro registre de test t
55 01 ÷
09 02 9
95 03 =
59 04 2nd Frac
65 05 x
26 06 2nd x=t? // x nul ?
15 07 ON/C // annule multiplication en cours
09 08 9
95 09 = // Termine calcul en cours s'il existe toujours
57.00 10 2nd FIX 0
13 11 R/S
Il est possible de gagner deux pas (ligne 00 et 10) en demandant à l'utilisateur de préparer sa calculatrice en tapant 2nd FIX 0 et 2nd C.T avant la première utilisation du code.
En postant ce code, je me rends compte qu'il y a moyen d'économiser encore un pas. Je vous laisse chercher comment.






