3 Les limites de l'approche descendante
1. Une calculatrice pour le grand Jules
1.6 Analyse de DECIMALISER .1 DECIMALISER ? Quoi faire ?
1.7.3 ROMANISER. Comment faire faire ?
On pourrait d'abord écrire en utilisant les deux variables RomainPlusGrandQue1000 et
RomainPlusPetitQue1000, toutes deux de type NombreRomain :
Si Decimal ≥ 4000 alors
ROMANISER_MORCEAU_SUPERIEUR_A_1000 RomainPlusGrandQue1000 de type NombreRomain
ROMANISER_MORCEAU_INFERIEUR_A_1000 RomainPlusPetitQue1000 de type NombreRomain Romain ← RomainPlusGrandQue1000 + RomainPluspetitQue1000 (1)
sinon
ROMANISER_DECIMAL
(1) Le signe + dénote ici la concaténation (= le fait de les coller l'une à l'autre) des deux chaînes de caractères RomainPlusGrandQue1000 et RomainPluspetitQue1000. La première de ces variables RomainPlusGrandQue1000 sert à contenir l'équivalent en chiffres romains du nombre de milliers de Decimal; la seconde RomainPluspetitQue1000 sert à contenir l'équivalent en chiffres romains de la partie de Decimal inférieure à 1000.
Pour mieux saisir ce que représentent les deux variables RomainPlusGrandQue1000 et
RomainPluspetitQue1000, il reste comme d'habitude à préciser les actions complexes apparues :
ROMANISER_MORCEAU_SUPERIEUR_A_1000
Decimal →
de type entier long
Transformer la partie multipliant 1000 de Decimal (le nombre de milliers de Decimal) en un nombre en chiffres romains, dont tous les symboles sont assortis
de ° et placer ce résultat dans
RomainPlusGrandQue1000
→ RomainPlusGrandQue1000 de type NombreRomain
avec
Avant Après
- Decimal de type entier long, contenant un entier entre 4000 et 998001
- RomainPlusGrandQue1000, de type NombreRomain contenant l'équivalent en chiffres romains assortis du symbole ° de la partie de Decimal multiple de 1000.
et
ROMANISER_MORCEAU_INFERIEUR_A_1000
Decimal →
de type entier long
Transformer la partie inférieure à 1000 de Decimal en un nombre en chiffres romains et placer ce résultat dans
RomainPlusPetitQue1000
→ RomainPlusPetitQue1000 de type NombreRomain avec
Avant Après
- Decimal de type entier long, contenant un entier entre 4000 et 998001
- RomainPlusPetitQue1000, de type NombreRomain contenant l'équivalent en chiffres romains de la partie de Decimal strictement inférieure à 1000.
On notera que pour chacune de ces actions, le paramètre Decimal contient un nombre supérieur à 4000, étant donné l'analyse de ROMANISER telle que conduite ci-dessus.
Et enfin :
ROMANISER_DECIMAL
Decimal →
de type entier long
Transformer Decimal en un nombre en chiffres romains
et placer ce résultat dans Romain → Romain
de type NombreRomain avec
Avant Après
- Decimal de type entier long, contenant un entier entre 0 et
3999
- Romain, de type NombreRomain contenant l'équivalent en chiffres romains de Decimal.
Une fois de plus, on peut unifier en une action unique ces diverses actions, même si l'écriture du symbole ° pour la partie de Decimal multiple de 1000 complique un peu la tâche.
Plutôt que de passer Decimal à ROMANISER_MORCEAU_SUPERIEUR_A_1000 en confiant à cette procédure le fait d'extraire la partie multipliant 1000 de Decimal et de la "romaniser" et de passer la même valeur Decimal à ROMANISER_MORCEAU_ INFERIEUR_A_1000 en demandant à cette procédure d'extraire la partie inférieure à 1000 et la "romaniser", nous allons en tout cas, lorsque Decimal est supérieur à 4000, commencer par isoler la partie de Decimal multiple de 1000, puis la partie inférieure à 1000 avant d'appeler à deux reprises une procédure unique de "romanisation" de ces deux "morceaux".
Il est facile de voir que cette action, que nous allons baptiser ROMANISER_TOUT_OU_PARTIE, doit en tout cas être assortie d'un paramètre "d'entrée" dans lequel nous passerons d'abord Decimal div 1000 (partie de Decimal multipliant 1000), puis Decimal mod 1000 (partie de Decimal inférieure à 1000) ou encore Decimal lui-même. Il nous faut aussi un paramètre de "sortie", baptisé Romain, qui sera, dans le premier cas un "prête-nom" pour
NombreRomainPlusGrandQue1000, dans le second cas un "prête-nom" pour NombreRomainPlusPetitQue1000, et enfin dans le troisième cas un "prête-nom" pour Romain
lui-même.
Il nous faut cependant un paramètre d'entrée supplémentaire qui signale si oui ou non la procédure ROMANISER_TOUT_OU_PARTIE reçoit la partie de Decimal multiple de 1000 (auquel cas il faut adjoindre aux caractères composant le nombre en chiffres romains obtenu, le symbole °).
Ainsi donc, l'action ROMANISER_TOUT_OU_PARTIE sera accompagnée de 2 paramètres d'entrée :
- Habituel, de type entier long, qui recevra le nombre décimal à transformer en nombre romain
- AuDelaDe1000, booléen, vrai lorsque le nombre passé dans Habituel constitue la partie
multiple de 1000 de Decimal et que dès lors les caractères du résultat doivent être accompagnés de °.
En effet, en l'absence d'un paramètre AuDelaDe1000 signalant s'il s'agit de transformer en chiffres romains la partie de Decimal multipliant 1000 ou la partie inférieure à 1000 ou encore
Decimal lui-même, la procédure ROMANISER_TOUT_OU_PARTIE ne "connaîtrait" et ne
travaillerait que sur la valeur donnée au paramètre Habituel sans "savoir" si la "romanisation" doit ou non accompagner les caractères romains du symbole °. Le simple fait de garnir le paramètre Habituel avec la valeur Decimal div 1000, avec Decimal mod 1000 ou avec Decimal, ne suffit pas pour que ROMANISER_TOUT_OU_PARTIE "sache" dans quel cas on se trouve. Ainsi ROMANISER_TOUT_OU_PARTIE recevant 68 comme valeur de Habituel ne peut savoir si 68 est la partie du nombre à transformer multipliant 1000 (auquel cas le symbole ° doit être adjoint aux chiffres romains) ou la partie inférieure à 1000 (auquel cas le symbole ° est inutile). Il faut donc un paramètre supplémentaire AuDelaDe1000 sur base duquel décider si ° doit ou non être adjoint.
Tout cela apparaîtra plus nettement encore lorsque je détaillerai (page 148) la manière dont s'effectuera le dialogue au moment d'un appel de procédure assortie de paramètres.
Il faut également un paramètre de sortie :
- Romain de type NombreRomain comportant l'équivalent en chiffres romains du nombre reçu
dans Habituel.
En résumé, nous avons donc :
ROMANISER_TOUT_OU_PARTIE(Habituel : entier long;
AuDelaDe1000 : booléen; var Romain : NombreRomain) Habituel →
de type entier long
AuDelaDe1000 → de type booléen
Transformer le nombre entier Habituel en son équivalent romain en plaçant à côté de chaque chiffre romain le
symbole ° lorsque AuDelaDe1000 est vrai et sans symbole ° dans le cas contraire. Dans tous les cas le
résultat obtenu doit être placé dans Romain.
→ Romain
de type NombreRomain
avec
Avant Après
- Habituel de type entier long contenant le nombre décimal à transformer; toujours compris entre 0 et 3999.
- AuDelaDe1000 , de type booléen, vrai lorsque les caractères du nombre romain à construire doivent être accompagnés de °.
- Romain , de type NombreRomain contenant l'équivalent en chiffres romains (accompagnés ou non de °) du contenu de
Habituel.
Avec cette description de l'action de "romanisation", on peut réécrire la marche à suivre correspondant à ROMANISER :
Si Décimal ≥ 4000 alors
ROMANISER_TOUT_OU_PARTIE (Decimal div 1000, vrai, RomainPlusGrandQue1000)
RomainPlusGrandQue1000 de type NombreRomain
ROMANISER_TOUT_OU_PARTIE (Decimal mod 1000, faux, RomainPlusPetitQue1000)
RomainPlusPetitQue1000 de type NombreRomain Romain ← RomainPlusGrandQue1000 + RomainPluspetitQue1000
sinon
Il faut une fois de plus mettre en parallèle la définition des paramètres de ROMANISER_TOUT_OU_PARTIE et ce qui leur est associé lors de chaque appel :
Définition: ROMANISER_TOUT_OU_PARTIE( Habituel; AuDelaDe1000; Romain)
1er appel: ROMANISER_TOUT_OU_PARTIE(Decimal div 1000, vrai, RomainPlusGrandQue1000)
Définition: ROMANISER_TOUT_OU_PARTIE( Habituel; AuDelaDe1000; Romain)
2è appel: ROMANISER_TOUT_OU_PARTIE(Decimal mod 1000, faux, RomainPlusPetitQue1000)
Définition: ROMANISER_TOUT_OU_PARTIE( Habituel; AuDelaDe1000; Romain)
3è appel : ROMANISER_TOUT_OU_PARTIE( Decimal, faux, Romain)
Autrement dit, au lieu de
- ROMANISER_MORCEAU_SUPERIEUR_A_1000, on appellera ROMANISER_TOUT_ OU_PARTIE en précisant que
- Habituel vaut Decimal div 1000
- AuDelaDe1000 est vrai
- Romain est RomainPlusGrandQue1000
au lieu de
- ROMANISER_MORCEAU_INFERIEUR_A_1000, on appellera ROMANISER_TOUT_ OU_PARTIE en précisant que
- Habituel vaut Decimal mod 1000
- AuDelaDe1000 est faux
- Romain est RomainPlusPetitQue1000
et enfin, au lieu de
- ROMANISER_DECIMAL, on appellera ROMANISER_TOUT_OU_PARTIE en précisant que
- Habituel vaut Decimal
- AuDelaDe1000 est faux
- Romain est Romain
Nous sommes dès lors, à ce stade, en mesure de répondre à