Fil d'Ariane
Mis à jour le mercredi 31 août 2016
  • 40 heures
  • Moyenne

Ce cours est visible gratuitement en ligne.

Ce cours existe en livre papier.

Ce cours existe en eBook.

Vous pouvez être accompagné et mentoré par un professeur particulier par visioconférence sur ce cours.

J'ai tout compris !

TP : convertir un nombre en toutes lettres

Connectez-vous ou inscrivez-vous pour bénéficier de toutes les fonctionnalités de ce cours !

Nous arrivons enfin au premier TP de ce cours ! Celui-ci a pour but de vous faire réviser et mettre en pratique l'essentiel de ce que vous avez appris dans les chapitres précédents, nous vous conseillons donc fortement de le lire et d'essayer de faire l'exercice proposé.

Dans les grandes lignes, ce TP vous permettra de réviser l'utilisation des variables, conditions, boucles, fonctions et tableaux. Il vous permettra aussi d'approfondir vos connaissances sur l'identification et la conversion des nombres.

Présentation de l'exercice

Ce TP sera consacré à un exercice bien particulier : la conversion d'un nombre en toutes lettres. Ainsi, si l'utilisateur entre le nombre « 41 », le script devra retourner ce nombre en toutes lettres : « quarante-et-un ». Ne vous inquiétez pas : vous en êtes parfaitement capables, et nous allons même vous aider un peu avant de vous donner le corrigé !

La marche à suivre

Pour mener à bien votre exercice, voici quelles sont les étapes que votre script devra suivre (vous n'êtes pas obligés de faire comme ça, mais c'est conseillé) :

  • L'utilisateur est invité à entrer un nombre entre 0 et 999.

  • Ce nombre doit être envoyé à une fonction qui se charge de le convertir en toutes lettres.

  • Cette même fonction doit contenir un système permettant de séparer les centaines, les dizaines et les unités. Ainsi, la fonction doit être capable de voir que dans le nombre 365 il y a trois centaines, six dizaines et cinq unités. Pour obtenir ce résultat, pensez bien à utiliser le modulo. Exemple : 365 % 10 = 5.

  • Une fois le nombre découpé en trois chiffres, il ne reste plus qu'à convertir ces derniers en toutes lettres.

  • Lorsque la fonction a fini de s'exécuter, elle renvoie le nombre en toutes lettres.

  • Une fois le résultat de la fonction obtenu, il est affiché à l'utilisateur.

  • Lorsque l'affichage du nombre en toutes lettres est terminé, on redemande un nouveau nombre à l'utilisateur.

L'orthographe des nombres

Dans le cas de notre exercice, nous allons employer l'écriture des nombres « à la française », c'est-à-dire la version la plus compliquée… Nous vous conseillons de faire de même, cela vous entraînera plus qu'en utilisant l'écriture belge ou suisse. D'ailleurs, puisque l'écriture des nombres en français est assez tordue, nous vous conseillons d'aller faire un petit tour ici afin de vous remémorer les bases.

À noter que vous n'êtes pas obligés de respecter toutes ces règles orthographiques, ce qui compte c'est que votre code puisse afficher les nombres en toutes lettres, les fautes orthographiques sont secondaires.

Tester et convertir les nombres

Afin que vous puissiez avancer sans trop de problèmes dans la lecture de votre code, il va falloir étudier l'utilisation des fonctions parseInt() et isNaN().

Retour sur la fonction parseInt()

Concernant parseInt(), il s'agit juste d'un approfondissement de son utilisation étant donné que vous savez déjà vous en servir. Cette fonction possède en réalité non pas un mais deux arguments. Le deuxième est très utile dans certains cas, comme celui-ci par exemple :

alert(parseInt('010')); // Affiche « 8 » sur certains navigateurs

Et là vous constatez que, sur certains navigateurs, le chiffre affiché n'est pas 10 comme souhaité mais 8 ! Pourquoi ? Tout simplement parce que la fonction parseInt() supporte plusieurs bases arithmétiques, ainsi on peut lui dire que le premier argument est en binaire. La fonction nous retournera alors le nombre en base 10 (notre propre base de calcul, le système décimal) après avoir fait la conversion base 2 (système binaire) → base 10 (système décimal). Donc, si nous écrivons :

alert(parseInt('100', 2)); // Affiche « 4 »

nous obtenons bien le nombre 4 à partir de la base 2, c'est bon !

Mais tout à l'heure le deuxième argument n'était pas spécifié et pourtant on a eu une conversion aberrante, pourquoi ?

Tout simplement parce que si le deuxième argument n'est pas spécifié, la fonction parseInt() va tenter de trouver elle-même la base arithmétique du nombre que vous avez passé en premier argument. Ce comportement est stupide vu que la fonction se trompe très facilement, la preuve : notre premier exemple sans le deuxième argument a interprété notre nombre comme étant en base 8 (système octal) simplement parce que la chaîne de caractères commence par un 0.

Bref, pour convertir correctement notre premier nombre, il nous faut indiquer à parseInt() que ce dernier est en base 10, comme ceci :

alert(parseInt('010', 10)); // Affiche « 10 »

Maintenant nous obtenons bien le nombre 10 ! Rappelez-vous bien ce deuxième argument, il vous servira pour le TP et, à n'en pas douter, dans une multitude de problèmes futurs !

La fonction isNaN()

Jusqu'à présent, pour tester si une variable était un nombre, vous utilisiez l'instruction typeof, sauf qu'elle pose problème :

var test = parseInt('test'); // Contient au final la valeur « NaN »
    
alert(typeof test); // Affiche « number »

Voilà le problème : notre variable contient la valeur NaN qui signifie Not a Number et pourtant l'instruction typeof nous renvoie « number » en guise de type, c'est assez contradictoire non ? En fait, typeof est limité pour tester les nombres, à la place mieux vaut utiliser la fonction isNaN() (is Not a Number) :

var test = parseInt('test'); // Contient au final la valeur « NaN »
    
alert(isNaN(test)); // Affiche « true »

Pourquoi true ? Tout simplement parce que isNaN() renvoie true quand la variable n'est pas un nombre, et false dans le cas contraire.

Il est temps de se lancer !

Vous voilà maintenant prêts à vous lancer dans l'écriture de votre code. Nous précisons de nouveau que les nombres à convertir vont de 0 à 999, mais rien ne vous empêche de faire plus si le cœur vous en dit. Évitez de faire moins, vous manqueriez une belle occasion de vous entraîner correctement. ;)

Bon courage !

Correction

Allez hop ! C'est fini ! Nous espérons que vous avez réussi à faire quelque chose d'intéressant, normalement vous en êtes parfaitement capables ! Le sujet est certes un peu tordu, mais vous avez largement assez de connaissances pour pouvoir le réaliser.

Toutefois, si vous avez bloqué alors que vous connaissiez très bien ce que l'on a appris dans les chapitres précédents, ne vous inquiétez pas : la programmation est un domaine où la logique règne en maîtresse (bon, d'accord, pas tout le temps !), il faut donc de l'expérience pour en arriver à développer de façon logique. Ce que nous voulons dire, c'est que si vous n'avez pas réussi à coder l'exercice aujourd'hui, ce n'est pas un drame ! Faites une pause, essayez de faire des exercices plus simples et revenez ensuite sur celui-ci.
De toute manière, c'est bien simple, si vous arrivez à lire et comprendre le corrigé que nous fournissons, alors vous êtes capables de réaliser cet exercice tout aussi bien que nous, voire même mieux !

Le corrigé complet

Voici donc la correction. Précisons que ce code n'est pas universel ! Il existe de nombreuses autres façons de coder cet exercice, et cette version n'est pas forcément la meilleure. Donc, si vous cherchez à recoder cet exercice après avoir lu le corrigé, ne refaites pas exactement la même chose ! Inventez votre propre solution, innovez selon vos propres idées ! Après tout, on dit qu'il existe autant d'algorithmes que de personnes dans le monde, car chacun possède sa propre façon de penser ; vous devriez donc être capables de réaliser une version de ce code en réfléchissant par vous-mêmes !

function num2Letters(number) {

    if (isNaN(number) || number < 0 || 999 < number) {
        return 'Veuillez entrer un nombre entier compris entre 0 et 999.';
    }

    var units2Letters = ['', 'un', 'deux', 'trois', 'quatre', 'cinq', 'six', 'sept', 'huit', 'neuf', 'dix', 'onze', 'douze', 'treize', 'quatorze', 'quinze', 'seize', 'dix-sept', 'dix-huit', 'dix-neuf'],
        tens2Letters = ['', 'dix', 'vingt', 'trente', 'quarante', 'cinquante', 'soixante', 'soixante', 'quatre-vingt', 'quatre-vingt'];

    var units = number % 10,
        tens = (number % 100 - units) / 10,
        hundreds = (number % 1000 - number % 100) / 100;

    var unitsOut, tensOut, hundredsOut;


    if (number === 0) {

        return 'zéro';

    } else {

        // Traitement des unités

        unitsOut = (units === 1 && tens > 0 && tens !== 8 ? 'et-' : '') + units2Letters[units];

        // Traitement des dizaines

        if (tens === 1 && units > 0) {

            tensOut = units2Letters[10 + units];
            unitsOut = '';

        } else if (tens === 7 || tens === 9) {

            tensOut = tens2Letters[tens] + '-' + (tens === 7 && units === 1 ? 'et-' : '') + units2Letters[10 + units];
            unitsOut = '';

        } else {

            tensOut = tens2Letters[tens];

        }

        tensOut += (units === 0 && tens === 8 ? 's' : '');

        // Traitement des centaines

        hundredsOut = (hundreds > 1 ? units2Letters[hundreds] + '-' : '') + (hundreds > 0 ? 'cent' : '') + (hundreds > 1 && tens == 0 && units == 0 ? 's' : '');

        // Retour du total

        return hundredsOut + (hundredsOut && tensOut ? '-' : '') + tensOut + (hundredsOut && unitsOut || tensOut && unitsOut ? '-' : '') + unitsOut;
    }

}



var userEntry;

while (userEntry = prompt('Indiquez le nombre à écrire en toutes lettres (entre 0 et 999) :')) {

    alert(num2Letters(parseInt(userEntry, 10)));

}

Essayer le code

Les explications

Vous avez le code, bien ! Mais maintenant il vous faut le comprendre, et on commence tout de suite !

Le « squelette » du code

Un code doit toujours posséder ce qui peut être appelé un « squelette » autour duquel il peut s'articuler, c'est-à-dire un code de base contenant les principales structures de votre script (comme un objet, une boucle, une fonction, etc.) que l'on va pouvoir étoffer au fur et à mesure de l'avancée du code. Dans notre cas, nous avons besoin d'une fonction qui fera la conversion des nombres, ainsi que d'une boucle pour demander à l'utilisateur d'entrer un nouveau nombre sans jamais s'arrêter (sauf si l'utilisateur le demande). Voici ce que ça donne :

function num2Letters(number) { // « num2Letters » se lit « number to letters », le « 2 » est une abréviation souvent utilisée en programmation
    // Notre fonction qui s'occupera de la conversion du nombre. Elle possède un argument lui permettant de recevoir les nombres en question.
}
	
var userEntry; // Contient le texte entré par l'utilisateur

while (userEntry = prompt('Indiquez le nombre à écrire en toutes lettres (entre 0 et 999) :')) {
	/*
	Dans la condition de la boucle, on stocke le texte de l'utilisateur dans la variable « userEntry ».
	Ce qui fait que si l'utilisateur n'a rien entré (valeur nulle, donc équivalente à false) la condition ne sera pas validée.
	Donc la boucle while ne s'exécutera pas et dans le cas contraire la boucle s'exécutera.
	*/
}
L'appel de la fonction de conversion

Notre boucle fonctionne ainsi : on demande un nombre à l'utilisateur qu'on envoie à la fonction de conversion. Voici comment procéder :

while (userEntry = prompt('Indiquez le nombre à écrire en toutes lettres (entre 0 et 999) :')) {
    
	/*
	On « parse » (en base 10) la chaîne de caractères de l'utilisateur pour l'envoyer ensuite
	à notre fonction de conversion qui renverra le résultat à la fonction alert().
	*/
	
	alert(num2Letters(parseInt(userEntry, 10)));
}
Initialisation de la fonction de conversion

Le squelette de notre code est prêt et la boucle est complète, il ne nous reste plus qu'à faire la fonction, le plus gros du travail en fait ! Pour vous expliquer son fonctionnement, nous allons la découper en plusieurs parties. Ici nous allons voir l'initialisation qui concerne la vérification de l'argument number et la déclaration des variables nécessaires au bon fonctionnement de notre fonction.

Tout d'abord, nous devons vérifier l'argument reçu :

function num2Letters(number) {
    
	if (isNaN(number) || number < 0 || 999 < number) { // Si l'argument n'est pas un nombre (isNaN), ou si le nombre est inférieur à 0, ou s'il est supérieur à 999
	    return 'Veuillez entrer un nombre entier compris entre 0 et 999.'; // Alors on retourne un message d'avertissement
	}
	
}

Puis nous déclarons les variables nécessaires à la bonne exécution de notre fonction :

function num2Letters(number) {
    
	// Code de vérification de l'argument […]
	
	
	/*
	Ci-dessous on déclare deux tableaux contenant les nombres en toutes lettres, un tableau pour les unités et un autre pour les dizaines. Le tableau des
	unités va du chiffre 1 à 19 afin de simplifier quelques opérations lors de la conversion du nombre en lettres. Vous comprendrez ce système par la suite.
	*/
	
	var units2Letters = ['', 'un', 'deux', 'trois', 'quatre', 'cinq', 'six', 'sept', 'huit', 'neuf', 'dix', 'onze', 'douze', 'treize', 'quatorze', 'quinze', 'seize', 'dix-sept', 'dix-huit', 'dix-neuf'],
	    tens2Letters = ['', 'dix', 'vingt', 'trente', 'quarante', 'cinquante', 'soixante', 'soixante', 'quatre-vingt', 'quatre-vingt'];
	
	
	/*
	Ci-dessous on calcule le nombre d'unités, de dizaines et de centaines à l'aide du modulo.
	Le principe est simple : si on prend 365 % 10 on obtient le reste de la division par 10 qui est : 5. Voilà les unités.
	Ensuite, sur 365 % 100 on obtient 65, on soustrait les unités à ce nombre 65 - 5 = 60, et on divise par 10 pour obtenir 6, voilà les dizaines !
	Le principe est le même pour les centaines sauf que l'on ne soustrait pas seulement les unités mais aussi les dizaines.
	*/
	
	var units = number % 10,
    	tens = (number % 100 - units) / 10,
    	hundreds = (number % 1000 - number % 100) / 100;
	
	
	// Et enfin on crée les trois variables qui contiendront les unités, les dizaines et les centaines en toutes lettres.
	
	var unitsOut, tensOut, hundredsOut;
	
}
Conversion du nombre en toutes lettres

Maintenant que notre fonction est entièrement initialisée, il ne nous reste plus qu'à attaquer le cœur de notre script : la conversion. Comment allons nous procéder ? Eh bien nous avons les unités, dizaines et centaines dans trois variables séparées ainsi que deux tableaux contenant les nombres en toutes lettres. Toutes ces variables vont nous permettre de nous simplifier la vie dans notre code. Par exemple, si l'on souhaite obtenir les unités en toutes lettres, il ne nous reste qu'à faire ça :

unitsOut = units2Letters[units];

Si ça paraît aussi simple c'est parce que notre code a été bien pensé dès le début et organisé de façon à pouvoir travailler le plus facilement possible. Il y a sûrement moyen de faire mieux, mais ce code simplifie quand même grandement les choses, non ? Maintenant notre plus grande difficulté va être de se plier à toutes les règles orthographiques de la langue française.

Bref, continuons !

Vous remarquerez que dans nos tableaux il n'y a pas le nombre « zéro ». Nous allons l'ajouter nous-mêmes à l'aide d'une condition :

function num2Letters(number) {
    
	// Code de vérification de l'argument […]
	
	// Code d'initialisation […]
	
	
	if (number === 0) {
	
	    return 'zéro'; // Tout simplement ! Si le nombre vaut « 0 » alors on retourne « zéro », normal !
	
	}
}

Maintenant nous devons nous occuper des unités :

function num2Letters(number) {

    // Code de vérification de l'argument […]

    // Code d'initialisation […]


    if (number === 0) {

        return 'zéro'; // Tout simplement ! Si le nombre vaut « 0 » alors on retourne « zéro », normal !

    } else { // Si « number » est différent de « 0 » alors on lance la conversion complète du nombre

        /*
        Ci-dessous on calcule les unités. La dernière partie du code (après le +) ne doit normalement pas vous poser de problèmes. Mais pour la
        condition ternaire je pense que vous voyez assez peu son utilité. En fait, elle va permettre d'ajouter « et- » à l'unité quand cette dernière
        vaudra 1 et que les dizaines seront supérieures à 0 et différentes de 8. Pourquoi ? Tout simplement parce que l'on ne dit pas « vingt-un »
        mais « vingt-et-un », cette règle s'applique à toutes les dizaines sauf à « quatre-vingt-un » (d'où le « tens !== 8 »).
        */

        unitsOut = (units === 1 && tens > 0 && tens !== 8 ? 'et-' : '') + units2Letters[units];

    }
}

Viennent ensuite les dizaines. Attention, ça se corse pas mal !

function num2Letters(number) {

    // Code de vérification de l'argument […]

    // Code d'initialisation […]


    if (number === 0) {

        return 'zéro'; // Tout simplement ! Si le nombre vaut « 0 » alors on retourne « zéro », normal !

    } else { // Si « number » est différent de « 0 » alors on lance la conversion complète du nombre


        // Conversion des unités […]


        /*
        La condition qui suit se charge de convertir les nombres allant de 11 à 19. Pourquoi cette tranche de nombres ?
        Parce qu'ils ne peuvent pas se décomposer (essayez de décomposer en toutes lettres le nombre « treize », vous nous
        en direz des nouvelles), ils nécessitent donc d'être mis un peu à part. Bref, leur conversion en lettres
        s'effectue donc dans la partie concernant les dizaines. Ainsi donc on va se retrouver avec, par exemple,
        « tensOut = 'treize'; » donc au final on va effacer la variable « unitsOut » vu qu'elle ne servira à rien.
        */

        if (tens === 1 && units > 0) {

            tensOut = units2Letters[10 + units]; // Avec « 10 + units » on obtient le nombre souhaité entre 11 et 19
            unitsOut = ''; // Cette variable ne sert plus à rien, on la vide

        }


        /*
        La condition suivante va s'occuper des dizaines égales à 7 ou 9. Pourquoi ? Eh bien un peu pour la même raison que la
        précédente condition : on retrouve les nombres allant de 11 à 19. En effet, on dit bien « soixante-treize » et
        « quatre-vingt-treize » et non pas « soixante-dix-trois » ou autre bêtise du genre. Bref, cette condition est donc chargée,
        elle aussi, de convertir les dizaines et les unités. Elle est aussi chargée d'ajouter la conjonction « et- » si l'unité
        vaut 1, car on dit « soixante-et-onze » et non pas « soixante-onze ».
        */
        else if (tens === 7 || tens === 9) {

            tensOut = tens2Letters[tens] + '-' + (tens === 7 && units === 1 ? 'et-' : '') + units2Letters[10 + units];
            unitsOut = ''; // Cette variable ne sert plus à rien ici non plus, on la vide

        }


        // Et enfin la condition « else » s'occupe des dizaines que l'on peut qualifier de « normales ».
        else {

            tensOut = tens2Letters[tens];

        }


        // Dernière étape, « quatre-vingt » sans unité prend un « s » à la fin : « quatre-vingts »

        tensOut += (units === 0 && tens === 8 ? 's' : '');

    }
}

Un peu tordu tout ça, n'est-ce pas ? Rassurez-vous, vous venez de terminer le passage le plus difficile. Nous nous attaquons maintenant aux centaines, qui sont plus simples :

function num2Letters(number) {

    // Code de vérification de l'argument […]

    // Code d'initialisation […]


    if (number === 0) {

        return 'zéro'; // Tout simplement ! Si le nombre vaut « 0 » alors on retourne « zéro », normal !

    } else { // Si « number » est différent de « 0 » alors on lance la conversion complète du nombre


        // Conversion des unités […]

        // Conversion des dizaines […]


        /*
        La conversion des centaines se fait en une ligne et trois ternaires. Ces trois ternaires se chargent d'afficher un
        chiffre si nécessaire avant d'écrire « cent » (exemple : « trois-cents »), d'afficher ou non la chaîne « cent » (si il
        n'y a pas de centaines, on ne l'affiche pas, normal), et enfin d'ajouter un « s » à la chaîne « cent » si il n'y a ni
        dizaines, ni unités et que les centaines sont supérieures à 1.
        */

        hundredsOut = (hundreds > 1 ? units2Letters[hundreds] + '-' : '') + (hundreds > 0 ? 'cent' : '') + (hundreds > 1 && tens == 0 && units == 0 ? 's' : '');
    }
}
Retour de la valeur finale

Et voilà ! Le système de conversion est maintenant terminé ! Il ne nous reste plus qu'à retourner toutes ces valeurs concaténées les unes aux autres avec un tiret.

function num2Letters(number) {

    // Code de vérification de l'argument […]

    // Code d'initialisation […]


    if (number === 0) {

        return 'zéro'; // Tout simplement ! Si le nombre vaut « 0 » alors on retourne « zéro », normal !

    } else { // Si « number » est différent de « 0 » alors on lance la conversion complète du nombre


        // Conversion des unités […]

        // Conversion des dizaines […]

        // Conversion des centaines […]


        /*
        Cette ligne de code retourne toutes les valeurs converties en les concaténant les unes aux autres avec un tiret. Pourquoi y a-t-il
        besoin de ternaires ? Parce que si on n'en met pas alors on risque de retourner des valeurs du genre « -quatre-vingt- » juste parce
        qu'il n'y avait pas de centaines et d'unités.
        */

        return hundredsOut + (hundredsOut && tensOut ? '-' : '') + tensOut + (hundredsOut && unitsOut || tensOut && unitsOut ? '-' : '') + unitsOut;
    }
}

Conclusion

La correction et les explications de l'exercice sont enfin terminées ! Si vous avez trouvé ça dur, rassurez-vous : ça l'était. ^^ Bon, certes, il existe des codes beaucoup plus évolués et compliqués que ça, mais pour quelqu'un qui débute c'est déjà beaucoup que de faire ça ! Si vous n'avez toujours pas tout compris, je ne peux que vous encourager à relire les explications ou bien refaire l'exercice par vous-mêmes. Si, malgré tout, vous n'y arrivez pas, n'oubliez pas que le Site du Zéro possède une rubrique consacrée au JavaScript dans le forum, vous y trouverez facilement de l'aide pour peu que vous expliquiez correctement votre problème.

Exemple de certificat de réussite
Exemple de certificat de réussite