A apprendre à programmer une HP48

Les derniers trucs auxquels vous avez joué, les derniers ordinateurs que vous avez bidouillés.

Modérateur : Politburo

Avatar du membre
C.Ret
Fonctionne à 9600 bauds
Fonctionne à 9600 bauds
Messages : 3404
Enregistré le : 31 mai 2008 23:43
Localisation : N 49°22 E 6°10

Re: A apprendre à programmer une HP48

Message par C.Ret »

Là je me doit d'intervenir !!!!


Pour dire que je suis à 100 % d'accord !

Parfois c'est pas deux semaines qu'il faut pour que l'auteur perde le fil de son programme, cela peut arriver du jour au lendemain !

En effet, en RPL, le listing d'un programme ne donne pas les informations essentielles qui permettraient de comprendre son fonctionnement. Le lecteur est constamment obligé de rétro-analyser le code qu'il a sous les yeux.

Même quelque chose comme << DUP SIN SWAP / >> nécessite une analyse minutieuse pour comprendre qu'une valeur est prise dans la pile puis remplacée par le résultat du calcul. Et c'est un calcul simple ! Dès que c'est compliqué, c'est très vite impossible ou fastidieux !
Sans compter les cas où le code étudié (on ne relit pas du RPL, on l'étudie) contient une instruction dont on ne connais pas le fonctionnement ou si celui-ci change en fonction des circonstances (drapeaux, types de données, etc...) !

C'est donc bien vrai que le RPL est un langage 'Write only' et souvent 'Write only at once'

Comme gégé, je suis très surpris que l'ordre immuable des arguments ne soit pas respecté avec les variables locales. On a bien 30 'A' STO ou 5 FIX (au lieu des STO 00 ou FIX 5 du RPN) mais pas « a b c → ... » ni « 1 9 a FOR ... »

Mais le plus grave c'est les mouvements de la pile avec n ROLL ou n PICK et autre OVER SWAP ROT DUPDUP qui opère sur quelque chose que l'on ne voit pas, qu'aucun élément dans le code ne permet de convenablement tracer. Sans compter la façon parfois abscons qu'on certains modèles à présenter le code avec des retours à la ligne forcés et la perte de toute indentation.
Comment faire apparaître tout les mouvements de la pile sans rendre les listing illisibles ??

Evidemment, l'absence de numéro repère dans les instructions interdit tout algorithme basé sur de subtiles GOTO comme dans d'autres langages (dont le RPN d'ailleurs). Mais bon ,le GOTO c'est le mal absolu ! Non ?
Image


Et enfin, je dois m'excuser, j'oublie qu'il existe des fous qui désactivent la fonction LAST ou UNDO ! Sur une HP-48, il n'y a d'après moi aucune raison de le faire, cette possibilité est héritée des HP-28C qui avaient trop peu de mémoire. Désactiver les fonctions LAST et autres UNDO étaient alors justifié lorsque l'on manipulait des matrices de grande taille. Et uniquement dans cet usage.
Désactiver le LAST sur HP28S, HP48s, HP48g, HP48sx, HP48gx, HP-48g+, HP50g n'est que pure folie !

Le type de folie que l'on aime bien avoir et qu'ont souvent les gens que l'on fréquente sur ce forum :)

A mon avis, aucune machine RPL ne succédera à l'HP50g à cause du manque de présentation fonctionnelle des listings RPL qui resteront à jamais de vagues listes d'instructions incompréhensibles et incohérentes entre guillemets.

Sinon, j'encourage ben à persévérer dans son apprentissage, le RPL est tout de même le langage de programmation puissant qui permet de tirer le meilleurs parti des machines en question. C'est une façon d'organiser données et codes très particulière qui convient bien à l'usage de ces systèmes.

Bon c'est pas tout, tous ces longs posts prennent du temps et je n'ai toujours pas compris ce que fait le programme de Ben.

Mais pour lister les carrés aux chiffres croissants, j'utiliserai, imprudent que je suis sur HP28/HP48, un truc du style :

Code : Tout sélectionner

« 1 9999 
  FOR n n SQ 99 
    IF OVER                       
      DO IP 10 / LAST MOD ROT MIN
        IF LAST >
        THEN DROP2 0 0 
        END SWAP
      UNTIL DUP 1 <
      END 
    THEN OVER 1 DISP
    END DROP2 
  NEXT 
»
ou

Code : Tout sélectionner

« 1 9999 
  FOR n n SQ → n2
    « 99 n2
      IF                       
        DO IP 10 / LAST MOD ROT MIN
          IF LAST >
          THEN DROP2 0 0 
          END SWAP
        UNTIL DUP 1 <
        END 
      THEN n2 1 DISP
      END DROP
    » 
  NEXT 
»
ATTENTION ! Il faut que la fonction de sauvegarde des arguments soit active et que donc LAST fonctionne !!!!

Oui, je sais, je suis imprudent.

Un inconvénient de ce programme est que les carrés déterminés s'affichent trop vite et ne sont pas mémorisés quelque part dans la calculette.
Mais comment corriger cela ?
SHARP PC-1211 PC-1360 EL-5150 PC-E500 | Commodore C=128D | Texas Instruments Ti-57LCD Ti-74BASICalc Ti-92II Ti-58c Ti-95PROCalc Ti-30XPROMathPrint | Hewlett-Packard HP-28S HP-41C HP-15C HP-Prime HP-71B | CASIO fx-602p | NUMWORKS | Graphoplex Rietz Neperlog | PockEmul | Sommaire des M.P.O. | Ma...dov'il sapone.
Ben
Fonctionne à 2400 bauds
Fonctionne à 2400 bauds
Messages : 1549
Enregistré le : 21 août 2016 19:04

Re: A apprendre à programmer une HP48

Message par Ben »

Un tout grand merci pour vos explications! Merci d'avoir pris le temps de me répondre :-)
C.Ret a écrit : 23 juil. 2017 07:42 j'encourage ben à persévérer dans son apprentissage
Ca me donne encore plus envie d'approfondir le langage! ;-)

Je me doute que ce premier programme n'est pas vraiment le plus adapté à la machine. C'est plus une traduction du programme BASIC qu'autre chose. Dans un premier temps, je ne vais pas lire les 2 exemples que tu viens de donner. Je vais d'abord assimiler les informations et le refaire en utilisant plus le stack. Je les lirais dans un 2e temps

Ben
Avatar du membre
C.Ret
Fonctionne à 9600 bauds
Fonctionne à 9600 bauds
Messages : 3404
Enregistré le : 31 mai 2008 23:43
Localisation : N 49°22 E 6°10

Re: A apprendre à programmer une HP48

Message par C.Ret »

Oui, c'est la difficulté quand on traduit d'un langage à l'autre, il est difficile de se défaire de la structure du programme source et de l'adapter aux spécificité du programme destination.

C'est parfois, plus facile de reprendre un peu de recul et de repartir d'une page blanche ou presque.

En particulier, l'astuce en RPL, c'est comme en RPN, de placer les objet dans le bon ordre dans la pile opérationnelle afin de faciliter les opération à réaliser.

Par exemple, si l'on a un compteur ou un accumulateur, il faut le laisser à coté du niveau qui va le remplir.
De même, les tests et les inflexions de l'algorithme dicte souvent ce que doit contenir la pile entre les points clefs du programme.

Par exemple:
Supposons que l'on veuille calculer la somme S pour n entier variant de a à b des 1/n²: le plus efficace sera d'avoir la somme en cours de calcul à coté de n. Il suffira alors d'ajouter la valeur n avec un séquence du type « n INV SQ + » qui fera progresser " d'un cran " le calcul de la somme.
Mais fera disparaître n de la pile.
Il faut donc prévoir quelque part un mécanisme pour garder n quelque part dans la pile afin de pouvoir l'incrémenter, tester si l'on a atteint la valeur supérieur b.
Il y a aussi le problème de l'initialisation des valeur de n et s au début du calcul. Il faudra bien initialiser en début de programme s à 0 et n à a.

Sans les structures en variable locale, il faut donc gérer l'agencement de la pile opérationnelle pour mémoriser a, b S et n.
Pour a, c'est facile, il disparaît dès l'initialisation de n. Par contre, le choix de la position de b dans la pile va rendre le code plus ou moins compliqué. Il y aura de nombreux SWAp ROT UNROT et autre réjouissant ROLL ou ROLLD, sans compter les DUP DUP2 ou OVEr pour effectuer des copie des valeur à conserver d'une étape à l'autre dans les boucles de calculs.

On devra sommer les valeurs 1/n² au fur et à mesure du calcul dans S, puis incrémenter n et vérifier qu'il n'a pas dépasser la valeur b. Comme on ne peut travailler qu'avec les premiers niveaux de la pile, les ROT UNROT et autre mouvements seront nécessaire pour orchestrer tout cela.
Les principaux écueils seront :
* la finalisation : Il faudra vider la pile des variable intermédiaire et ne laisser que S comme résultat. Ce qui sera fait par un simple DROP2 qui expurgera la pile de n et b. Ce choix implique l'ordre final dans la pile.
* le sens du test : attention en RPL, pour tester n et b, le sens du comparateur dépend de l'ordre de n et b dans les niveau 1: et 2: de la pile !
* l'incrémentation de n : doit se faire avant le test et n doit " remonter " ( ou descendre, on ne sait toujours pas) au niveau 1:
* la formule itérative S+1/n² --> S nécessite que S et la copie de n (pour ne pas l'effacer soit en haut de la pile (niveau 1: et 2:)
* l'initialisation de la boucle TANT/QUE (DO ... UNTIL ... END ) L'ordre des éléments dans la pile doit être le même au niveau du Do et du END, c'est la contrainte majeure pour ce type de structure.

Voici un exemple de code correspond à ces stratégie. Les différents choix dans l'ordre des élément contenu par la pile dépend à la fois des contrainte lié au fait que les instruction n'opères que sur les premier niveaux de la pile, et les choix personnels dans l'organisation de la pile et une certaines habitudes ou réflexe d'optimisation (qui parfois sont de vrai poison).
Il y a donc certainement tout un tas d'autres façon de faire. Aucune n'est mieux qu'une autre, sauf au regard d'un critère spécifique.

J'ai numéroté les instructions en hexadécimal pour faire un peu comme dans les programmes RPN; Au-dessous de chaque instruction, est indiqué le contenu de la pile afin de suivre pas à pas le cheminement de toutes les variables du programme.

Code : Tout sélectionner

     001    002 003 004  005 006  007 008   009 00A 00B   00C  00D 00E 00F   010  
5:                                                               S
4:             ┌───┐       b   b    b             S              b   S┌───┐
3:     b      0│  S│  b    n   n    n   b     S   b   S     S    n   n│  S│
2: a   a      b│  b│  n    S   S    S   n     b   n   b     b    b   b│  b│
1: b   0      a│  n│  S    n 1/n 1/n²   S     n   1   n     n    n b<n│  n│    S   S 1:
     « 0  UNROT│ DO│ROT OVER INV   SQ   + UNROT   1   + UNTIL DUP2   <│END│DROP2  »
               └───┘                                                  └───┘

Avec lune structure en variable locale, les choses sont simplifiée, surtout avec une boucle FOR ... NEXT sur n:

Code : Tout sélectionner

      001    002 003 004 005 006 007 008 009  00A 00B  00C 
3:                         S
2: a                   S   a┌───┐      S   S    S    ┌────┐  
1: b               S   a   b│  S│      n 1/n 1/n²   S│   S│    S  :1
     « → a b   «   0   a   b│FOR│  n   n INV   SQ   +│NEXT│  » 
                            └───┘                    └────┘ 
Les principaux écueils sont évité et la taille de la pile reste minimale, rendant tout mouvement dans celle-ci inutile.

On remarquera que seules les paramètres (a b) et variables intermédiaires (n) sont locales, la variable intermédiaire qui donnera le résultat S (que j'ai mis en majuscule dès le début) est toujours pris en charge par la pile car elle constitue un résultat qui sera rendu aux niveau antérieur justement par la pile. Ceci évite tout risque d'un recours à tout 's' STO.

Mais le RPL est malléable, et rien n'interdit d'utiliser justement ce type de structure :

Code : Tout sélectionner

      001 002      003 004 005 006  007 008  009 00A 00B  00C 00D 00E 00F 010 011 012   
3:      a             ┌───┐                                                  ┌───┐
2: a    b             │   │                            1                n    │   │
1: b    0             │   │  n 1/n 1/n²   S        1   n            n   b n>b│   │  S     S :1
     «  0  → n b s   «│ DO│  n INV   SQ 's' STO+   1 'n' STO+ UNTIL n   b   >│END│  s  »
                      └───┘                                                  └───┘
On retrouve alors les paradigmes de programmation des langages sans pile opérationnelle, comme le BASIC ou le C :

Code : Tout sélectionner

10: INPUT A,B : S=0  :  DO  :  S=S+1/N^2   : N = 1+N   : LOOP UNTIL N>B  :  PRINT S : END


Voilà, sans publier le mouvement des éléments dans la pile, le problème majeur des codes en RPL est que les opérations importantes sont cachées et que la seule édition du code ne permet jamais de facilement et rapidement retrouver ce qui s'y passe.
On ne lit pas un programme en RPL, on l'analyse. C'est vite pénible en fait.

Heureusement, le RPL a d'autres avantages. Une fois que la difficulté du codage est passée, les nouvelles instructions s'intègrent pleinement au système et viennent compléter celui-ci d'instructions spécifiques à l'usage de chacun.
Ce qui fait, que télécharger des instruction ou des programmes permet facilement d'étendre à l'infini les possibilités des ces machines dans la résolution quotidienne et efficace des problèmes dans toute une gamme de domaines d'applications professionnelles, scientifiques et autres domaines d'ingénieuse riz.
SHARP PC-1211 PC-1360 EL-5150 PC-E500 | Commodore C=128D | Texas Instruments Ti-57LCD Ti-74BASICalc Ti-92II Ti-58c Ti-95PROCalc Ti-30XPROMathPrint | Hewlett-Packard HP-28S HP-41C HP-15C HP-Prime HP-71B | CASIO fx-602p | NUMWORKS | Graphoplex Rietz Neperlog | PockEmul | Sommaire des M.P.O. | Ma...dov'il sapone.
Avatar du membre
C.Ret
Fonctionne à 9600 bauds
Fonctionne à 9600 bauds
Messages : 3404
Enregistré le : 31 mai 2008 23:43
Localisation : N 49°22 E 6°10

Re: A apprendre à programmer une HP48

Message par C.Ret »

Je reposte le listing du code proposé le 23 juillet, mais en présentant les mouvements de la pile.

Code : Tout sélectionner

    000    001    002    003    004    005    006    007    008    009    00A    00B    00C    00D    00E    00F
5:                    ┌─────┐                                   ┌─────┐                         n²
4:                    │     │                                   │     │           n²             m     n²     n²
3:                    │     │                                n² │   n²│    n²      m     n²   ab.c      m   ab.c
2:                  1 │     │                  n²     n²      m │    m│     m    abc      m    abc   ab.c      c
1:           1   9999 │     │     n     n²      m      m  abcde │abc.d│   abc     10   ab.c     10      c      m
      «      1   9999 │FOR n│     n     SQ     99     IF   OVER │   DO│    IP     10      /   LAST    MOD    ROT
                      └─────┘                     _______       └─────┘

Code : Tout sélectionner

    010    011    012    013    014    015    016    017    018    019    01A    01B    01C    01D    01E    01F
5:                 n²        ┌─────┐                     ┌─────┐                         n²       ┌──────┐┌─────┐
4:               ab.c     n² │     │                     │     │                  n²      m     n²│      ││     │
3:   n²     n²      m   ab.c │   n²│                  n² │   n²│    n²     n²      m   ab.c      m│    n²││     │
2: ab.c   ab.c      c      m │ ab.c│           n²      0 │    0│     m      m   ab.c   ab.c   ab.c│     m││   n²│
1:    m      m      m    c>m │    m│    n²      0      0 │    0│  ab.c   ab.c   ab.c      1 ab.c<1│  ab.c││≠0  m│
    MIN     IF   LAST      > │ THEN│ DROP2      0      0 │  END│  SWAP  UNTIL    DUP      1      <│   END││ THEN│
           ____              └─────┘                     └─────┘       _______                    └──────┘└─────┘

Code : Tout sélectionner

    020    021    022    023    024    025    026 
5:                     ┌────┐       ┌─────┐
4:          n²         │    │       │     │
3:   n²      0         │    │       │     │
2:    m     n²      n² │  n²│       │     │
1:   n²      1      m  │   m│       │     │
   OVER      1   DISP  │ END│ DROP2 │ NEXT│     »
                       └────┘       └─────┘
Les encadrements, mettent en évidence les correspondancse dans l'étagement des objets dans la pile qu'il ne faut pas "louper" justement à cause des boucles ( :D des "loop" #ENG - Ce jeu de mot ne fait rire que moi apparemment ! - :mrgreen: ):



J'aime bien cette présentation des listings RPL, ils sont plus facile à décortiquer.
SHARP PC-1211 PC-1360 EL-5150 PC-E500 | Commodore C=128D | Texas Instruments Ti-57LCD Ti-74BASICalc Ti-92II Ti-58c Ti-95PROCalc Ti-30XPROMathPrint | Hewlett-Packard HP-28S HP-41C HP-15C HP-Prime HP-71B | CASIO fx-602p | NUMWORKS | Graphoplex Rietz Neperlog | PockEmul | Sommaire des M.P.O. | Ma...dov'il sapone.
Répondre

Retourner vers « A quoi t'as joué hier ? »