Calculatrices


Le RPL. (Texte d'HP mâd)





Le RPL ou LISP Polonais Inversé est un langage développé pour la HP28 puis adapté à la HP48. Ce langage basé sur le jonglage avec des types abstraits de données ou objets est d'une puissance et d'une simplicité inégalées .



Le principe de base du RPL est très simple. Il consiste à l'automatisation de tâches à taper au clavier.Prenons comme exemple une suite d'instructions destinées à incrémenter le nombre au niveau 1 de la pile. "1 +". Le programme réalisant la même opération sera tout simplement 1 + . Il suffit de spécifier que c'est un programme et le tour est joué .



Je vais donc tout simplement me borner à vous donner la 'liste' des instructions RPL spécifiques à la programmation (et évidement vous apprendre comment vous en servir). Pour ce qui est des instructions 'classiques', je me bornerai à vous renvoyer à l'annexe G de votre manuel d'utilisation où vous trouverez la liste des instructions RPL classiques.



Parmi les instructions que je vais vous expliquer, il en existe 2 sor s appelés 'Structures de contrôle'. Tant que vous ne les maitrisez pas, inutile d'essayer de programmer en assembleur, ou en external, car ces structures constituent la BASE de la programmation.

Comment entrer un programme.



Bon, alors, gros naze! Pour allumer ta HP, tu appuies avec ton indexe droit sur la touche en bas à gauche portant l'inscription ON.



Ensuite tu appuies sur la touche Shift Lavande (orange pour SX) qui se trouve deux touches au-dessus du ON, puis sur la touche-.



tu te retrouves avec les symboles et le curseur qui clignote. Tu peux alors taper ton programme.




Les instructions de tests



Je parlerai beaucoup de programmes sortant un 0 ou un réel >1. Voici ceux qui sont implémentés en machineIl existe plusieurs tests sur HP:



  • Le diffèrent # Shift bleu 1



  • L'égal == Shift rouge 1



  • L'inférieur


  • Le supérieur > Shift bleu 2



  • L'inférieur ou égal <= Shift rouge 3



  • Le supérieur ou égal >= Shift bleu 3



  • qui réalisent un test sur des objets comparables (réels, binaires). les == et différents s'appliquent sur tout objet et testent s'ils sont pareils.



    On peut aussi utiliser les opérations logiques sur les 0 et le 1: AND, OR, XOR et NOT afin de réaliser le test voulu.



    Il faut noter aussi que beaucoup d'instructions renvoient un 0 ou autre chose, par exemple POS qui renvoie la position, ou un 0, ce qui évite des tests inutiles en sortie. Par exemple exécuter toto si la chaîne contient la sous-chaine.



    IF
        "AA" POS
    THEN
    toto
    END

    Les boucles.



    Le boucles sont des structures de contrôle qui permettent de répéter une action, soit un certain nombre de fois, soit jusqu'à un événement, soit tant que certaines conditions sont remplies.



    Il existe trois sortes de boucles qui servent dans des cas différents.

    La boucle FOR

    Généralités



    La boucle FOR s'applique dans les cas où l'on doit faire v ier un indice d'une valeur de départ à une valeur de fin connue à l'avance. Par exemple, si on cherche le plus grand élément d'un tableau, on devra 'scanner' tous les éléments du tableau (il y en à évidemment N), donc on aura besoin d'une variable qui prendra successivement toutes les valeurs de 1 à N.



    En RLP, la syntaxe du FOR est la suivante:



    2: Indice de départ @ Un réel
    1:    Indice de fin    @ Un autre réel
    FOR Variable    @ Ici, on indique le nom de la variable
        Instructions à répéter
    NEXT



    Exemple de programme: Afficher les entiers de 1 à 500



    1 500    @ On boucle de 1 à 500
    FOR a    @ La variable qui sert de compteur est a
        a@ On met le contenu de a sur la pile
        1 DISP        @ L'instruction DISP affiche l'objet du niveau 2 de la pile à la ligne donnée par le réel au niveau 1
        NEXT    @ Et la fin de boucle

    1e extension du FOR

    Le STEP en pas constant (avant ou arrière)


    Dans certains cas, on peut désirer boucler, non p de 1 vers 500, mais de 500 vers 1 (parcourir les indices à l'envers). Ceci est évidement possible grâce à l'instruction STEP. Cette instruction remplace le NEXT. Si nous analysons le NEXT, que fait-il exactement? Il incrémente la variable, et si elle est inférieur à l'indice de fin, il reéxécute les instructions de la boucle.



    Le STEP, va permettre d'incrémenter la variable d'une autre valeur que 1. Par exemple: '2 STEP' fera: Variable = Variable + 2 ....



    Donc en faisant



    500
    1
    FOR a
    -1 STEP



    On boucle de 500 à 1, donc à reculons.



    on peut aussi faire la somme des 100 premiers nombres impairs .



    0        @ au début, la somme est nulle
    1        @ on boucle de 1
    201    @ à 201
    FOR a @ boucle sur a
        a        @ mise de a sur la pile
    +        @ ajout de a à la somme
    2 STEP    @ et on STEP

    Le STEP en pas variable


    Autre intérêt du STEP, le pas peut être donné par un programme. Imaginons un programme d'étude de fonction et la fonction suivante:



    Cette fonction peut se diviser en 3 zones: 2 zones où elle est très complexe, où elle varie beaucoup et une 3e où elle est presque droite.



    Si je fais un programme destiné à étudier cette fonction en plusieurs points, je n'ai pas besoin de l'étudier sur des intervalles aussi petits dans la zone 2 que dans les zones 1 et 3. Comme je fais mon étude sur les points qui sont donnés par l'indice d'une boucle FOR, je peux concevoir une petite routine qui calculera le pas entre une itération et la suivante (par exemple avec un calcul de la dérivée en ce point).



    Ce qui donne



    0 50    @ J'étudie ma fonction sur
    @ l'interval 0 50
    FOR a    @ Boucle
        Etude de la fonction en a
            Calcul du pas pour l'étude suivante
            STEP    @ et le STEP dont la valeur est donnée par le calcul du dessus

    2e extension du FOR: Le START



    Il se peut que l'on n'ait pas soin d'indice de bouclage; par exemple si l'on veut faire 50 fois un calcul de probabilité pour vérifier l'exactitude de notre estimation ; on n'a pas besoin d'un indice, on veut juste faire le calcul 50 fois; le START est tout indiqué, il fonctionne exactement comme le FOR sauf qu'il n'y a pas d'indice.



    1 50
    START    @ Je boucle 50 fois
    Calcul
    NEXT



    On peut évidemment faire un START STEP, mais cela ne sert strictement à rien car le seul intérêt du STEP est de modifier l'indice.

    La boucle While



    Je ne m'étendrai pas sur cette boucle 102 ans, elle est toute simple. On l'utilise dans les cas où on doit traduire une structure du type: Tant que ceci, Fais cela. Par exemple, si j'ai devant moi pleins de filles à la queue leu leu, Tant que la fille en premier a les yeux bleus, je passe à la suivante.



    C'est-à-dire sur HP



    WHILE
        a les yeux bleus
    REPEAT
        On passe à la suivante
        END



    Le programme qui remplacera le "a les eux bleus" devra laisser sur la pile un réel soit nul: elle n'a pas les yeux bleus, ou un réel supérieur a 1: elle a les yeux bleus.



    Autre exemple



    WHILE
        maman dit: "tu n'iras pas au cinéma"
    REPEAT
        "Maman je veux aller au cinéma voir
            ROCKY V "
    END

            

    La boucle DO



    Je ne m'étendrai pas sur cette boucle 102 ans , elle est toutes simple aussi. on l'utilise dans les cas où on doit traduire une structure du type: Je fais ça jusqu'à ce que ceci. Par exemple je tape sur le type en face jusqu'à ce que j'ai mal aux mains.



    C'est-à-dire sur HP



    DO
        Tape sur le mec
    UNTIL
        J'ai mal aux mains
    END



    Le programme qui remplacera le "j'ai mal aux mains" devra laisser sur la pile un réel soit nul: "j'ai pas mal aux mains", ou un réel supérieur a 1: "Putain, ça fait mal!!!!".



    Autre exemple



    DO
        Range une chose de ta chambre
    UNTIL
        Ta chambre est rangée
    END

    Différences fondam tales entre le While et le DO.



    La différence est très simple, dans le While, on teste d'abord où on met les pieds "While y a pas de merde devant moi REPEAT j'avance END", alors qu'avec un DO, je mets le pied dedans.



    Evidemment, mes exemples sont excessifs, mais il sont très démonstratifs et amusants!!

    Les Tests

    Le IF THEN ELSE standard



    La structure de tests et le IF THEN ELSE END. C'est-à-dire: Si cela, alors toto, sinon titi.



    sur HP cela donne



    IF
        Test @ Ce programme doit renvoyer un
            @ 0 ou un réel > 1
    THEN
        Programme si test vrai
    ELSE
        Programme si test faux
    END



    exemple



    IF
        A 1 ==
    THEN
        "A=1" 1 DISP
    ELSE
        "A diffèrent de 1" 1 DISP
    END



    le ELSE est optionnel, on peut faire juste



    IF
        A B ==
    THEN
        A 1 DISP
    END

    Le IFERR.



    Sur la HP , il existe une instruction fort pratique et fort dégeulasse permettant de tester si n programme conduit à une erreur. C'est le IFERR



    IFERR
        Programme
    THEN
        Action à exécuter en cas d'erreur
    ELSE
        Action à exécuter si pas d'erreur
    END



    Comme je l'ai clairement indiqué, il permet d'affecter une action à une erreur survenue dans un programme donné.



    Exemple



    IFERR
        /
    THEN
        "On ne peut diviser par 0" 1 DISP
    END

    Le Case.



    Cette structure permet d'effectuer une action spécifique pour chaque possibilité que peut prendre une variable.



    CASE
        DUP 1 ==
        THEN
    DROP "A=1" 1 DISP
        END
        DUP 2 ==
        THEN
    DROP "A=2" 1 DISP
        END
        DUP 3 ==
        THEN
    DROP "A=3" 1 DISP
        END
        DUP 4 ==
        THEN
    DROP "A=4" 1 DISP
        END
        DROP
        "A n'est pas égal à 1, 2,3 ou 4" 1 DISP
    END



    On remarque une cause de défaut à la fin (a différent de ...).



    Cette structure peut paraître excellente, mais on fait plus rapide.

    Les IFT, IFTE et S ed Case

    Structure IFT et IFTE



    Ces instructions permettent les mêmes chose que les IF THEN ELSE END, mais elles sont utilisables dans les expressions 'algebraic' et sont plus rapides. De plus, elles correspondent plus à la notion de pile.



    Structure du IFTE



    3: Résultat d'un test
    2: Programme à exécuter si vrai
    1: Programme à exécuter si faux
    IFTE



    Structure du IFT



    2: Résultat d'un test
    1: Programme à exécuter si vrai
    IFT



    Un autre avantage du IFTE est que le programme à exécuter peut venir d'un autre programme, il y a modularité.

    Le Speed Case.



    Ce n'est pas une structure de la HP, c'est une bidouille de programmeurs destinée à accélérer le case. Elle se sert des instructions POS et GET pour simplifier le case.



    {     Programme par défaut
         Programme si cas 1
         Programme si cas 2
        ........................
         Programme si cas N
    }
    {    Cas 1
        Cas 2
        .....
        Cas N
    }
    ROT
    POS
    1
    GET EVAL



    Ce bout de programme prend au niveau 1 l'objet à tester et évalue le programme voulu.



    Il pause sur la pile la liste des programmes et la liste des cas, il met au niveau 1 l'objet à tester (ROT), il recherche sa position dans la liste des cas (POS), il ajoute 1 (s'il n'est pas dans la liste, POS renvoie 0; comme dans la liste des programmes le programme 0 est le programme par défaut, le programme 2 dans le cas 1 ETC, tout colle pile-poil) il récupère le programme à exécuter (GET) et il l'évalue (EVAL).

    Les variables locales.

    Introduction.



    Sur la HP48, il existe deux sortes de variables: Les variables locales et les variables globales. Vous connaissez tous les variables locales, c'est celles ou vous stockez vos gruges (les variable du menu VAR koi!). Les variables locales ne sont pas stokes en VAR, elles sont directement en RAM. Les variables locales sont uniquement accessibles dans un programme. Elles servent au programmeur pour stoker des données tem rairement. Mais me direz vous , pourquoi ne pas utiliser les variable globales.Il vaut mieux utiliser des variables locales dans un programme et ceci pour 3 raisons:
    Elles sont prévues pour ca.
    Elles sont plus rapide en accès.
    Elles se 'gèrent' toutes seules.
    La consommation mémoire est moindre.
    Elles permettent l'empilement et donc la récursivité.

    Utilisation des variables locales.



    Si l'on veut utiliser des variables locales dans un programme, il faut d'abord les 'déclarer'. C'est a dire qu'il faut dire a la HP les identificateurs qui sont des variables locales de manière a les différencier des variables globales.



    -> A B C    @ Je déclare et j'initialise
                @ A, B et C

        Programme utilisant A, B et C



    Ici, on vois un bout de programme déclarant de 3 variables locales A, B et C qui pourrons être utilisées dans le programme .



    La déclaration sert aussi d'initialisation, c'est a dire que si je fait 5 3 1 -> A B C ... , cela déc rera A, B et C et les initialisera respectivement a 5, 3 et 1 .



    Ces variables aurons une existence entre l'ouverture du programme et sa fermeture, mais des le programme ferme, elles seront 'purgées'.



    Dans le programme, je peut me servir de A, B et C comme variables, je peut me servir de toutes les fonction de traitement des variables sur elles (INCR, DECR, STO, STO+, STO-, ...) mais pas de PURGE car elles s'effacent toutes seules a la fin du programme. Il faut aussi savoir que contrairement a une globale, l'appel d'une locale correspond a un RCL et non a un EVAL. Si je stocke un programme dans une globale et que je l'appelle, le programme sera évalué, alors que si je place un programme dans une locale et que je l'appel, le programme sera pose sur la pile .



    PS: On peut aussi déclarer une expression algébrique utilisant des locales:
    -> A B C 'A+B+SIN(C-A^B*COS(C-A))'

    Notions d'empilement.



    Les variables locales peuvent s'empiler, c'est a dire que l'on peut dans un programme ilisant une variable locale déclarer un autre programme utilisant des locales.. Ces locales peuvent de plus avoir le même nom, on n'a alors accès qu' a la dernière .



        45 -> A
         65 15 -> A B
                12 -> B
        A B    @ Renvoie 65 et 12
                
    A B    @ Renvoie 65 et 15
            
            A    @ Renvoie 45 (Ici, B n'existe pas)
        



    Vous me direz que cela ne sert a rien qu'il suffit de ne pas faire des locales avec le même nom.



    Mais il se trouve que si une fonction ce rappelle luis même, ce qui correspond a une technique de programmation appelée récursivité, si cette fuction déclarer des locales, a chaque appel récursif, elle crée de nouvelles variable portant le même nom.

    Exemple d'utilisation.



    Voici un petit exemple de programme récursif. c'est a dire qu'il comporte une petite procédure qui se rappelle elle même. Cette procédure est stockée dans la variable locale R ce qui permet de ne pas avoir deux programmes: in programme d'initialisation et un pro amme contenant la procédure. On peut y remarquer la petite 'bidouille' permettant de le faire. On n'initialise pas la variable R avec la procédure car cela obligerait a se servir de R alors que l'on a pas encore déclarer que c'était une locale. Par contre, une fois le programme ouvert, on peut taper une programme contenant R qui sera alors considérée comme une variable locale.



        9 { # 0h # 0h }
        PVIEW (20,20) (2,0) 0
        -> C D R
         (0,1) SWAP
                IF DUP
    THEN 1 - (0,1)
                OVER R EVAL C DUP D +
    DUP 'C' STO LINE SWAP
                'D' STO* (0,-1) SWAP
                R EVAL
                ELSE DROP2
                END
            
            DUP 'R' STO
            EVAL
        



    Autre exemple, celui si est fort cours (mais des plus utiles). Il prend sur la pille un nom (local, global ou un nom d'objet de port), et envoi l'objet qui y est contenu. l'intérêt est surtout pour les librairie car on peut alors les envoyer sans être oblige de les recopier en VAR, c'est a dire que l'on a pas besoins de deux foi la RAM pour les envoyer.



        -> A
         'A' SEND
        

    Gros problèmes des locales, et comment les résoudre.

    Le problème.


    Imaginons que je suis en train de faire un gros programme avec pleins de sous programmes dans des variables a part, je ne peut pas me servir dans un sous programme des variables locales définies par le programme appelant.



    si j'ai le programme TOTO suivant:



        1 -> A
            TITI



    Je ne peut pas me servir de A dans TITI car lorsque l'on stocke le programme dans TITI, la HP ne sait pas que c'est un sous programme de TOTO, et donc elle ne sait pas que le A sera une variable locale et non une variable globale.



    Le problème est donc de trouver un système pour pouvoir quand même utiliser A dans TITI.Il y a deux solutions au problème: celle que nous avons trouve, et l'anti bug bonux mis au point par HP dans la HP48Gx.

    Le système HPuser .


    La réflexion est simple: Dans le programme TO , A existe en tant que variable locale, donc si je met un HALT dans TOTO, lorsque la HP me rendra la main, elle sera encore dans TOTO et donc A existera, donc si j'édite TITI a ce moment, il prendra aussi le A pour une variable locale et non une variable Globale. le tour est alors joue.

    Le système HP (Sur G uniquement).


    Chez HP, ils on adopter une autre solution, ils on décidés de différencier les variables locales des variables globales. Ainsi sur HP48Gx, une variable commencent par <- est une variable locale. Donc si je fait



        -> <-A
            TITI



    <-A est utilisable dans TITI sans avoir a utiliser le bidouille HPuser.





    © Copyright 1999 FTLS (Tyndiuk Frédéric). All rights reserved.
    Last Update 08/03/2000 - Send all comments to webmaster@ftls.org