Je n'ai jamais été très fort en math (ni dans les
autres matières), et je me perds parfois avec les nombres
dès que je dois les traiter dans le monde informatique. C'est
pourquoi je me suis dit qu'il serait peut-être pratique de
constituer une petite synthèse permettant de s'y retrouver un
peu entre bits, octets, mots, surtout quand on doit s'attaquer à
des conversions entre les différents types. Si j'ai fini par
comprendre comment tout cela fonctionnait, je pense que vous aussi ne
devriez pas avoir trop de difficulté pour y parvenir.
Codage des nombres en informatique
Dans le monde informatique, qui au niveau processeur ne sait
reconnaitre que des valeurs logiques de type tout ou rien (0 ou 1), il
est fréquent de travailler avec des
nombres, catégorisés selon leur grandeur. Ainsi, on peut
travailler
avec un nombre qui ne peut prendre que deux valeurs comme le bit, tout comme on peut travailler avec des nombres qui peuvent prendre 256 valeurs différentes comme l'octet
(byte en anglais, à ne pas confondre avec bit), ou encore avec
des nombre de valeurs encore plus grandes. D'un point de
vue machine, tous les nombres sont décrits par un nombre plus ou
moins important de bits, car il n'y a pas moyen de faire autrement.
Plus un nombre a une valeur elevée, et plus le nombre de bits
nécessaires pour le "faire tenir" peut être important.
Type de nombre
Nombre de "fils" (de bits)
Nombre de possibilités
Bit
1
2 (0 ou 1)
Octet
8
256 (de 0 à 255)
Word
16
65536 (de 0 à 65535)
DWord
32
La catégorisation d'un nombre est simple : si on peut le faire
tenir dans un petit "casier" (par exemple casier de type Octet), on se
contente de ce type de casier, qui ne prend pas trop de place. S'il ne
peut pas y tenir, on le met dans un casier plus grand (par exemple
casier de type Word), qui prend certes plus de place mais qui devient
nécessaire. Bien sûr, un nombre de faible valeur (par
exemple 34) peut aussi bien tenir dans un petit casier (byte, dans
lequel on peut ranger des nombres dont la valeur maximale est 255) que
dans un grand casier (word, dans lequel on peut ranger des nombres dont
la valeur maximale est 65535).
Element binaire soliste : le bit
Comme déjà dit, l'élement binaire de base
appelé bit peut prendre deux valeur, soit 0 soit 1. C'est une
chose assez facile à assimiler, car comme le montrent les
schémas suivants, on peut avec un seul fil, une pile, une
ampoule et un interrupteur, transmettre visuellement l'information
binaire 0 (ampoule L1 éteinte) ou l'information binaire 1
(ampoule L1 allumée) grâce à l'interrupteur SW1.
Premier élement binaire combiné à un second élement binaire : 2 bits
Si maintenant on ajoute au dispositif précédent une
seconde ampoule L2 et un second interrupteur SW2, on multiplie par 2 le
nombre de possibilités visuelles.
Le simple fait d'ajouter une troisième ampoule L3 et un
troisième interrupteur SW3 va encore multiplier par deux le
nombre de combinaisons possibles, et l'ajout d'une quatrième
ampoule L4 et d'un quatrième interrupteur SW4 double encore le
nombre de possibilités. Bref, à chaque fois que l'on
ajoute une composante de base (interrupteur + ampoule), on multiplie
par deux le nombre de combinaisons. On ne dirait pas comme ça,
mais avec quelques interrupteurs et quelques ampoules
supplémentaires, on peut très vite atteindre un nombre de
combinaisons très important. A titre d'exemple, on peut
atteindre 256 combinaisons possibles avec 8 ampoules (appelons-les
désormais des bits), et 65536 combinaisons possibles avec 16
ampoules (16 bits). Il est aisé de dire qu'à chaque
ampoule correspond le nombre 1 quand elle est allumée ou le
nombre 0 quand elle est éteinte, mais ce n'est pas suffisant
pour décrire pleinement le nombre que chaque combinaison
représente. Si on reprend l'exemple précédent avec
nos deux ampoules L1 et L2, on voit que l'on dispose d'un "code binaire
brut" égal à 00, 01, 10 ou 11, mais ces nombres, qui
correspondent à une notation en base 2, ne sont pas
immédiatement représentatifs du nombre décimal
(base 10) qui leur correspond et que l'on a plus d'aisance à
manipuler car plus commun dans nos activités de tous les jours.
C'est pourquoi on doit faire correspondre à chaque ampoule
(à chaque bit) une valeur qui lui est sienne et qui n'appartient
à aucune autre. A l'ampoule L1, on peut attribuer la valeur 1,
et à l'ampoule L2 on peut attribuer la valeur 2. On peut ensuite
additionner la valeur des ampoules allumées, et ne pas du tout
tenir compte des ampoules éteintes. Cela pourrait donner la
chose suivante :
Si les deux ampoules sont éteintes, on obtient une valeur totale
égale à 0 car aucune des valeurs propres à chaque
ampoule n'est prise en compte, elles sont toutes ignorées. Si
l'ampoule L1 est seule allumée, on ne tient compte que de sa
valeur propre, qui est égale à 1. Si l'ampoule L2 est
seule allumée, on ne tient compte que de sa valeur propre, qui
est égale à 2. Et si les deux ampoules L1 et L2 sont
allumées, on additionnent entre elles les deux valeurs de 1 et
2, ce qui donne 3. Nous disposons bien de 4 valeurs totales
(décimales) possibles, avec 2 ampoules seulement (2 bits), ces
valeurs peuvent être comprises entre 0 et 3.
Ecriture en 8 bits
Si maintenant nous utilisons 8 ampoules (8 bits), le nombre de
combinaisons possibles est de 256. Nous n'allons pas dessiner toutes
ces combinaisons car l'encre d'imprimante coûte cher, mais nous
pouvons prendre un exemple parmi d'autres, schématisé sur
le croquis suivant.
Si on ne prend en compte que les lampes allumées et que l'on
additionne leurs valeurs respectives, on aboutit à la somme
totale de 45. En effet, rien de plus simple, il suffit de raisonner de
la façon suivante :
- La valeur totale vaut pour le moment 0 (zéro)
- La lampe L1 est allumée, on ajoute sa valeur qui est 1
à la valeur totale actuelle qui est 0 : on obtient la valeur
totale de 1
- La lampe L2 est éteinte, on n'ajoute rien à la valeur
totale actuelle qui est 1 : la valeur totale reste à 1
- La lampe L3 est allumée, on ajoute sa valeur qui est 4 à la valeur
totale actuelle qui est 1 : on obtient la valeur totale de 5
- La lampe L4 est allumée, on ajoute sa valeur qui est 8 à la valeur
totale actuelle qui est 5 : on obtient la valeur totale de 13
- La lampe L5 est éteinte, on n'ajoute rien à la valeur
totale actuelle qui est 13 : la valeur totale reste à 13
- La lampe L6 est allumée, on ajoute sa valeur qui est 32 à la valeur
totale actuelle qui est 13 : on obtient la valeur totale de 45
- La lampe L7 est éteinte, on n'ajoute rien à la valeur
totale actuelle qui est 45 : la valeur totale reste à 45
- La lampe L8 est éteinte, on n'ajoute rien à la valeur
totale actuelle qui est 45 : la valeur totale reste à 45
C'est ainsi qu'on en déduit qu'un nombre binaire écrit
"00101101" (c'est ce qu'on lit pour les lampe en partant de L8 en
allant vers L1) est équivalent en valeur au nombre
décimal écrit "45". Autre exemple :
Si comme précédemment on ne prend en compte que les lampes allumées et que l'on additionne
leurs valeurs respectives, on aboutit à la somme totale de 194.
- La valeur totale vaut au départ 0 (zéro)
- La lampe L1 est éteinte, on n'ajoute rien à la valeur
totale actuelle qui est 0 : la valeur totale reste à 0
- La lampe L2 est allumée, on ajoute sa valeur qui est 2 à la valeur
totale actuelle qui est 0 : on obtient la valeur totale de 2
- La lampe L3 est éteinte, on n'ajoute rien à la valeur
totale actuelle qui est 2 : la valeur totale reste à 2
- La lampe L4 est éteinte, on n'ajoute rien à la valeur
totale actuelle qui est 2 : la valeur totale reste à 2
- La lampe L5 est éteinte, on n'ajoute rien à la valeur
totale actuelle qui est 2 : la valeur totale reste à 2
- La lampe L6 est éteinte, on n'ajoute rien à la valeur
totale actuelle qui est 2 : la valeur totale reste à 2
- La lampe L7 est allumée, on ajoute sa valeur qui est 64 à la valeur
totale actuelle qui est 2 : on obtient la valeur totale de 66
- La lampe L8 est allumée, on ajoute sa valeur qui est 128 à la valeur
totale actuelle qui est 66 : on obtient la valeur totale de 194
Ainsi,
un nombre binaire écrit "11000010" est équivalent en valeur au nombre
décimal écrit "194".
Remarques
- Les lampes et interrupteurs sont numérotés de 1
à 8, mais il est aussi commun dans la profession de les
numéroter de 0 à 7. Cela ne change strictement rien
à la façon de "décoder" la valeur binaire pour en
obtenir son équivalent décimal, mais peut parfois
embrouiller les esprits. Ne vous laissez pas faire !
- La lampe numérotée L1 est ce qu'on appelle le poids
faible, car sa valeur propre est la plus petite de toutes les lampes.
La lampe numérotée L8 est appelée le poids fort,
car sa valeur propre est la plus grande de toutes les lampes. Si la
lampe L8 est la seule allumée, le résultat final a plus
de poids (128) que si seule la lampe L1 est allumée
(résulat final de valeur 1).
Encore plus de bits !
Et on peut ainsi aller plus loin avec le nombre de bits, pour passer
à 32 bits, 64 bits, 128 bits, 256 bits, etc. Avec 16 bits, nous
disposons déjà de 65536 combinaisons (valeurs
décimales) possibles, ce qui est déjà très
confortable pour bien des applications. Comme la valeur (le poids) de
la neuvième lampe L9 sera le double de celle qui la
précède (lampe L8), sa valeur sera de 256 (128 * 2). La
valeur de L10 sera le double soit 512, et ainsi de suite jusqu'à
la seizième ampoule L16 qui se voit attribuer la valeur de 32768.
Un nombre binaire écrit "0011001100000001" est équivalent en valeur au nombre
décimal écrit "13057".
Notation héxadécimale
La
notation hexadécimale permet d'écrire une valeur "longue" avec peu de
caractères. Le principe de "réduction" visant à simplifier l'écriture
d'un nombre binaire ou décimal est assez simple, il suffit de retenir
qu'un caractère alphanumérique compris entre 0 et 9 ou compris entre A
et F est attribuée à chaque paquet de 4 bits, ce qui explique que les
octets sont toujours écrits sous la forme $xx (le symbole $ permet
juste de spécifier qu'il s'agit d'un nombre exprimé en hexadécimal, il
ne joue aucun rôle dans la valeur qui suit). Un octet comportant 8
bits, il est nécessaire d'utiliser deux caractères pour le
décrire. La correspondance entre paquet de 4 bits, caractère
hexadécimal et
valeur décimale répond à ce qui suit :
Les
exemples suivants montrent des correspondances entre nombres binaires,
nombres hexa et nombres décimaux, il s'agit dans ce cas d'octets (8
bits) dont la valeur peut être comprise entre 0 et 255.
C'est
bien gentil tout ça, il est effectivement très simple d'effectuer les
conversions entre valeurs binaires et valeurs hexa. Mais comment
effectuer la conversion directe entre hexa et décimal - dans un sens ou
dans l'autre, sans passer par la valeur binaire ?
Conversion hexa vers décimal d'un octet
C'est le plus simple. -
on convertit le premier caractère alphanumérique (chiffre ou lettre) en
son équivalent décimal grâce à la liste de conversion vue précédement. - on multiplie cette valeur par 16 - on convertit le second caractère alphanumérique en son équivalent décimal - on additionne cette seconde valeur à celle obtenue ci-avant.
Exemple avec la valeur hexa $3F - le caractère 3 en hexa correspond à la valeur 3 en décimal - on multiplie la valeur décimale 3 par 16, on obtient 48 - le caractère F en hexa correspond à la valeur 15 en décimal - on additionne les deux valeurs 48 et 15, on obtient la valeur 63. $3F = 63d
Exemple avec la valeur hexa $B6 - le caractère B en hexa correspond à la valeur 11 en décimal - on multiplie la valeur décimale 11 par 16, on obtient 176 - le caractère 6 en hexa correspond à la valeur 6 en décimal - on additionne les deux valeurs 176 et 6, on obtient la valeur 182. $B6 = 182d
Conversion décimal vers hexa d'un octet
Il existe plusieurs méthodes, voici la mienne : - on divise la valeur décimale par 16, la partie entière correspond au premier caractère de la valeur hexa; -
on multiplie la partie fractionnaire (ce qu'il y a après la virgule)
par 16, et on obtient le second caractère de la valeur hexa.
Exemple avec la valeur décimale 12 - on divise 12 par 16, on obtient une partie entière égale à 0, le première caractère hexa est donc 0. - on multiplie la partie fractionnaire par 16, ce qui donne 0,75 * 16 = 12, le second caractère hexa est donc C. La valeur Hexa du nombre décimal 12 est donc $0C.
Exemple avec la valeur décimale 143 - on divise 143 par 16, on obtient une partie entière égale à 8, le première caractère hexa est donc 8. - on multiplie la partie fractionnaire par 16, ce qui donne 0,9375 * 16 = 15, le second caractère hexa est donc F. La valeur Hexa du nombre décimal 12 est donc $8F.
Remarque
: si la valeur décimale à convertir est strictement inférieure à 16,
c'est encore plus simple, il suffit de convertir cette valeur en sa
représentation hexa, et d'ajouter un 0 (zéro) devant. Par exemple, la
conversion en hexa de la valeur décimale 8 est $08, et la conversion en
hexa de la valeur décimale 15 est $0F.
Remplacement des ampoules par des fils d'entrée / sortie standards
Les petits schémas qui précèdent mettent en avant
des lampes qui s'allument ou qui restent éteintes, mais on peut
imaginer avoir à leur place, des pattes de circuits
intégré (entrées logiques ou sorties logiques),
par exemple. Dans ce cas, la mesure de tension faite sur chaque patte
renseigne sur l'état logique de chacune d'elle, il est d'usage
de trouver du +5 V pour un état logique haut (1, lampe
allumée) et de trouver 0 V pour un état logique bas (0,
lampe éteinte). Mais dans la pratique, ces valeurs peuvent bien
sûr différer un petit peu (quelques millivolts
d'écart), voir s'en écarter totalement si la tension
d'alimentation des circuits intégrés n'est pas de 5 V
mais de 3,3 V ou moins. Mais la règle générale
veut qu'un circuit intégré logique alimenté sous
une tension de X volts présente une tension égale
à ou voisine de X volts sur ses sorties placées à
l'état haut, et présente une tension égale
à ou voisine de 0 V pour les sorties placées à
l'état bas. Il en est de même pour les entrées, qui
doivent recevoir une tension égale à ou voisine de X
volts pour un état haut et une tension égale à ou
proche de 0 V pour un état bas.