Apprendre C++ avec Qt : Annexe 0 Combien avez-vous de doigts ?
Il est peu probable que vous utilisiez le langage C++ trs longtemps sans tre confront des nombres reprsents autrement que sous leur forme habituelle. Mme si les changements de reprsentation dont il va tre question ici sont trs loin d'tre d'un usage quotidien, une certaine familiarit avec ces questions est certainement bnfique (ne serait-ce que pour vous viter d'avoir l'impression qu'on vous cache quelque chose !). Il faut mme avouer qu'il n'est pas tout fait exclu que vous soyez un jour confront une situation o une vritable matrise de ces techniques s'avre indispensable. 1 - Les tres humains Nous avons l'habitude d'utiliser un systme numrique positionnel de base 10.
Ce systme est dit "de base 10" parce qu'il utilise 10 chiffres : 0, 1, 2, 3, 4, 5, 6, 7, 8 et 9.
Il est dit positionnel parce que le "poids" d'un chiffre, c'est dire la valeur qu'il exprime, dpend de sa position. Ainsi, dans 1999, les trois occurrences du chiffre 9 n'ont pas la mme signification : il s'agit respectivement de neuf sicles, neuf dcennies et neuf annes.
Plus gnralement, dans un systme positionnel, un chiffre figurant dans un nombre a un poids gal la base leve la puissance correspondant au nombre de chiffres figurant sa droite. Illustrons ce principe en analysant un exemple :
criture du nombre en base 10 1 9 9 9
Pour chaque colonne, il est ais de dterminer combien de colonnes figurent sa droite : nombre de chiffres droite 3 2 1 0
Avec ce nombre, nous pouvons calculer le poids de chaque colonne : poids = base nombre de chiffres droite 10 3 = 1000 10 2 = 100 10 1 = 10 10 0 = 1
1999 veut donc, en fait, dire : total (1* 1000) + (9 * 100) + (9 * 10) + (9 * 1)
Il semble que l'adoption de la base 10 soit lie au fait que nous avons (normalement) cinq doigts chaque main, soit un total de 10. Comme ces doigts peuvent facilement tre utiliss pour compter (grce leur capacit se plier et se dplier relativement indpendamment les uns des autres), le dnombrement jusqu' 10 ne pose pas de gros problme. Au-del de 10, il faut noter combien de fois on a puis son stock de doigts, d'o l'apparition des notions de dizaine, puis de centaine (dizaine de dizaines), etc. Il n'en reste pas moins qu'on compte les secondes et les minutes par soixantaines, les heures par 24 et les hutres la douzaine
Pour ce qui est du principe positionnel, il apparat pour la premire fois Babylone, 2000 ans avant notre re, mais ne s'est gnralis que beaucoup plus rcemment (le systme romain, que nous utilisons encore dans certains cas, n'est pas positionnel). Une des difficults souleves par le principe de position est qu'il implique l'usage du zro, concept qui n'est arriv maturit qu'en Inde, 500 ans aprs JC ! 2 - Les ordinateurs Si l'on conserve le principe positionnel tout en se limitant l'utilisation de deux chiffres (0 et 1, par exemple), on obtient le systme binaire. Comme dans le cas de la base 10, la reprsentation du premier-entier-plus-grand-que-le-plus-grand-des-chiffres ncessite le recours une position supplmentaire. Le dbut de la suite des entiers est donc reprsent ainsi : 0, 1, 10, 11, 100, 101
La simple application du principe des poids permet de transformer trs facilement l'criture binaire d'un nombre en criture en base 10. Prenons l'exemple de 1011 :
Document du 16/11/05 - Retrouvez la version la plus rcente sur http://www.up.univ-mrs.fr/wcpp C++ - Annexe 0 Combien avez vous de doigts ? 2/4 Ecriture binaire du nombre 1 0 1 1 nombre de chiffres droite 3 2 1 0 poids = base nombre de chiffres droite 2 3 = 8 2 2 = 4 2 1 = 2 2 0 = 1 total (exprim en base 10) (1 * 8) + (0 * 4) + (1 * 2) + (1 * 1) = 11
Ou, si vous prfrez, une huitaine plus zro "quatraine" plus une paire plus une unit font onze.
La transcription inverse n'est gure plus difficile : il suffit de partir de la gauche et, pour chaque colonne 1 , de vrifier si le nombre restant exprimer est ou non aussi grand que le poids. Lorsque c'est le cas, il faut mettre un 1 dans cette colonne et retrancher de la quantit restant exprimer le poids de la colonne. Essayons d'crire en binaire le nombre qui s'crit 5 en base 10 :
nombre de chiffres droite 3 2 1 0 poids = base nombre de chiffres droite 2 3 = 8 2 2 = 4 2 1 = 2 2 0 = 1
Comme 5 est infrieur 8, la colonne de poids 8 contient 0 : 5 est infrieur 8 0
Comme 5 est suprieur 4, la colonne de poids 4 contient 1. Ce 1 reprsente en fait une "quatraine", ce qui veut dire qu'il nous reste 5 moins une "quatraine", c'est dire 1. 5 est suprieur 4 il reste exprimer : 5 4 = 1 1
Le nombre qu'il nous faut maintenant exprimer (1) est infrieur 2. La colonne des paires contient donc 0. 1 est infrieur 2 0
La colonne des units reoit finalement 1 pour reprsenter la quantit qui nous reste. 1 est gal 1 1 Ecriture binaire du nombre 0 1 0 1
En d'autres termes, 5 vaut "zro huitaine, une quatraine, zro paire et une unit".
L'criture binaire prsente l'avantage de pouvoir tre plaque directement sur les systmes de mmoire dont les composants ont deux tats stables (cf. Leon 1). Pour un usage humain, il faut bien reconnatre que les nombres crits de cette faon sont peu lisibles, surtout cause du fait qu'ils deviennent vite trs longs : 1999, par exemple, s'crit 0111 1100 1111 en binaire (il est d'usage, pour des raisons qui apparatront dans quelques instants, de regrouper les chiffres binaires par paquets de 4). Mme en informatique, on n'utilisera donc ce type d'criture que dans des cas trs particuliers, par exemple lorsque les chiffres eux-mmes, et non la valeur du nombre, revtent une importance spciale.
Le langage C++ n'autorise malheureusement pas l'usage de la reprsentation binaire des nombres dans les textes sources. 3 - Les programmeurs S'il faut renoncer la reprsentation binaire pour des raisons de confort, l'alternative a priori la plus sduisante est certainement l'criture habituelle (en base 10). C'est effectivement le systme qui est utilis dans la plupart des cas. Il arrive toutefois que la reprsentation en base 10 s'avre peu pratique, parce qu'elle prsente peu d'affinits avec la reprsentation binaire. Le systme le plus gnralement employ dans ces circonstances est la reprsentation hexadcimale (c'est dire en base 16).
Pour pouvoir crire les nombres en utilisant une base suprieure 10, il faut disposer de plus de 10 symboles pour reprsenter les chiffres. Plutt que d'inventer des symboles originaux, on choisit habituellement les lettres de l'alphabet, et, dans le cas de l'hexadcimal, il nous faut donc mobiliser les lettres de A F 2 . Un avantage vident de ce choix est que tout le monde connat dj l'ordre de ces symboles et est donc en mesure de reconstruire la table d'quivalences suivante :
1 Il faut, bien entendu, utiliser un tableau ayant assez de colonnes ! (Le poids de la colonne la plus gauche doit tre au moins gal au nombre qu'il s'agit de reprsenter.) 2 On utilise indiffremment les majuscules et les minuscules J-L Pris - 16/11/05 C++ - Annexe 0 Combien avez vous de doigts ? 3/4
chiffre hexadcimal A B C D E F criture en base 10 10 11 12 13 14 15 (de 0 9, le systme hexadcimal utilise les chiffres habituels)
Le choix de lettres pour figurer les chiffres suprieurs 9 prsente aussi un aspect divertissant : certains nombres cessent de ressembler des nombres. La reprsentation hexadcimale de celui que vous connaissez sous la forme 51 966 en est un exemple bien connu, et si vous rencontrez un jour 14 600 926, 16 435 934 ou 251 636 974 crits en hexadcimal, vous aurez certainement un instant d'hsitation avant de vous convaincre qu'il s'agit bien de nombres.
La retranscription en base 10 d'un nombre crit en hexadcimal est tout aussi facile que celle d'un nombre crit en binaire. La seule difficult concerne, au moment du total, la conversion des chiffres suprieurs 9 l'aide du tableau prcdent :
Ecriture hexadcimale du nombre 1 A 8 C nombre de chiffres droite 3 2 1 0 poids = base nombre de chiffres droite 16 3 = 4096 16 2 = 256 16 1 = 16 16 0 = 1
Une "quatre-mille-quatre-vingt-seizaine" plus dix "deux-cent-cinquante-sixaines" plus huit "seizaines" plus douze units font six mille sept cent quatre vingt seize ?
De mme, la mthode employe pour crire un nombre en hexadcimal ne diffre de celle utilise pour le binaire qu'en un point : lorsque la quantit restant exprimer dpasse le poids de la colonne, ce n'est pas 1 qu'il faut placer dans cette colonne, mais le rsultat de la division entire de la quantit par le poids (si ce rsultat est suprieur 9, il faudra utiliser le chiffre hexadcimal correspondant). Exprimons en hexadcimal l'anne de la prise de la Bastille :
nombre de chiffres droite 3 2 1 0 poids = base nombre de chiffres droite 16 3 = 4096 16 2 = 256 16 1 = 16 16 0 = 1 1789 est infrieur 4096 0 1789 / 256 = 6 il reste exprimer : 1789 (256 * 6) = 253 6 253 / 16 = 15 il reste exprimer : 253 (16 * 15) = 13 15 13 / 1 = 13 13 Ecriture hexadcimale du nombre 0 6 F D
Dans un contexte informatique, la base 16 prsente un intrt parce qu'un seul chiffre hexadcimal contient exactement la mme quantit d'information qu'un groupe de quatre chiffres binaires. En d'autres termes, un nombre hexadcimal deux chiffres correspond exactement un octet. Cette proprit 3 se traduit concrtement de deux faons : le passage d'une reprsentation binaire une reprsentation hexadcimale (ou d'une reprsentation hexadcimale une reprsentation binaire) est trs facile et, mieux encore, ce type de transcription est souvent inutile !
L'quivalence chiffre hexadcimal/nombre quatre chiffres binaires permet de dcomposer les transcriptions : pour passer d'une reprsentation hexadcimale une reprsentation binaire, il suffit de remplacer chaque chiffre hexadcimal par les quatre chiffres binaires correspondant, et les chiffres hexadcimaux peuvent tre traits indpendamment les uns des autres. Inversement, pour retranscrire un nombre exprim en binaire en notation hexadcimale, il suffit de regrouper les chiffres binaires par paquets de 4 (en commenant par la droite, et en compltant gauche avec des 0, si c'est ncessaire) et de remplacer chaque paquet par le chiffre hexadcimal correspondant. Les programmeurs qui font un usage intensif de ces oprations connaissent les quivalences par cur, et les autres utilisent une table qu'il est facile de reconstituer en cas de besoin :
Hex 0 1 2 3 4 5 6 7 8 9 A B C D E F Bin 0000 0001 0010 0011 0100 0101 0110 0111 1000 1001 1010 1011 1100 1101 1110 1111
3 Il s'agit d'une consquence assez directe du fait que 16 est la quatrime puissance de 2. J-L Pris - 16/11/05 C++ - Annexe 0 Combien avez vous de doigts ? 4/4 Voici, par exemple, comment on peut transcrire en binaire le nombre qui s'crit F3 58 A9 02 en hexadcimal :
F 3 5 8 A 9 0 2 1111 0011 0101 1000 1010 1001 0000 0010
Vous pouvez vous convaincre dfinitivement de la simplicit des transcriptions entre hexadcimal et binaire en essayant de retrouver l'criture en base 10 du nombre utilis dans l'exemple prcdent. Vous pouvez partir soit de sa forme binaire (1111 0011 0101 1000 1010 1001 0000 0010), soit de sa forme hexadcimale (F3 58 A9 02), mais, si vous n'utilisez pas de calculette, l'effort et le temps ncessaires seront dmesurs par rapport ceux exigs par le passage de l'hexadcimal au binaire (ou inversement).
Souvent, il n'est mme pas ncessaire de procder la moindre transcription, car les caractristiques intressantes sont directement visibles dans le nombre hexadcimal.
Une de ces caractristiques importantes est le nombre de cases mmoires ncessaires pour stocker un nombre. Imaginons par exemple que nous avons stocker une quantit entire positive dont nous savons qu'elle n'excdera jamais 16 777 507. Combien d'octets de mmoire faut-il consacrer ce stockage ? Le simple nombre de chiffres utiliss pour crire un nombre en base 10 ne permet pas de savoir quelle sera la longueur de sa transcription binaire (qui dtermine la place occupe en mmoire). La rponse cette question serait en revanche immdiate si la limite tait exprime en hexadcimal : 1 00 01 23 ne tient pas sur trois octets, il en faut donc en prvoir quatre 4 .
L'expressivit de l'criture hexadcimale devient encore plus importante lorsque l'information stocke en mmoire n'a aucune signification numrique. La transcription du binaire en base 10 lui fait alors perdre certaines particularits qui sont au moins en partie conserve en hexadcimal. Prenons comme exemple la squence binaire 101010101010101. L'alternance parfaite des 1 et des 0 y saute aux yeux. Il peut s'agir d'un pur hasard, mais il est galement possible que cette rgularit ait une signification. Au cours d'une opration de dbugage, de tels patterns "trop beaux pour tre vrais" attirent souvent l'attention et permettent parfois de trouver l'origine du problme. Si la squence en question est prsente sous la forme d'un nombre 5 crit en base 10, c'est 21 845, et cette squence de chiffres ne prsente absolument rien de remarquable. Sous forme hexadcimale, c'est 55 55, et le lecteur a de bonnes chances d'y dtecter une rgularit (avec un peu d'habitude, l'alternance des 1 et des 0 y est mme presque plus visible que dans la forme binaire).
La notation hexadcimale tant, dans bien des cas, la meilleure faon de "montrer le binaire", le langage C++ offre la possibilit de l'utiliser directement dans les textes sources. Il suffit qu'une squence de chiffres soit prcde par les deux caractres "0x" (le chiffre zro et la lettre x minuscule) pour que le compilateur interprte la squence comme reprsentant un nombre en hexadcimal.
const i nt SEI ZE = 0x10; / / i ni t i al i se cor r ect ement l a const ant e SEI ZE 4 - Conclusion Si, la question pose par le titre, vous n'avez rpondu ni "10" ni "16", mais "0x10", flicitations ! Vos seize doigts vous permettent une matrise quasi-naturelle de l'hexadcimal, ce qui vous ouvre un brillant avenir dans l'industrie du logiciel. Dans le cas contraire, inutile d'apprendre le prsent document par cur, mais essayez tout de mme de vous souvenir d'o vous le rangez, on ne sait jamais
4 On peut mme aller plus loin : le quatrime octet n'aura jamais une valeur suprieure 1. On n'utilise donc effectivement qu'un seul de ses huit bits. Le nombre 1 00 01 23 occupe donc exactement 1 + (3 * 8) = 25 bits. 5 Si le contenu de la mmoire n'a "aucune signification numrique", pourquoi serait-il prsent sous la forme d'un nombre (quelle que soit la base choisie) ? C'est une bonne question, et la seule rponse honnte me semble tre : "Normalement, il ne devrait pas tre reprsent ainsi. Mais si vous tes en train de dbuger, c'est justement parce que rien ne se passe normalement" Lorsqu'on ne sait plus comment l'interprter, prsenter l'information sous forme de nombres crits en hexadcimal est le meilleur compromis qu'on ait trouv pour obtenir la concision qui fait cruellement dfaut la reprsentation binaire, sans pour autant sacrifier tout rapport direct avec la ralit du codage, comme le fait la reprsentation en base 10. J-L Pris - 16/11/05