Code : Tout sélectionner
Tutorial 3 - Les changements de base, les nombres entiers signés
----------------------------------------------------------------
Par Oliv & Denis
- Terminé le 05 novembre 2004 -
-------------------------------
Les bases, suite :
------------------
Le changement de bases peut être très utile. Avant de voir les méthodes pour changer de
bases, voici un tableau qui récapitule les 20 premiers chiffres des bases binaire,
décimale, hexadécimale.
____________________________________
| Binaire | Décimale | Hexadécimale |
|___________________________________|
| 0 | 0 | 0 |
| 1 | 1 | 1 |
| 10 | 2 | 2 |
| 11 | 3 | 3 |
| 100 | 4 | 4 |
| 101 | 5 | 5 |
| 110 | 6 | 6 |
| 111 | 7 | 7 |
| 1000 | 8 | 8 |
| 1001 | 9 | 9 |
| 1010 | 10 | A |
| 1011 | 11 | B |
| 1100 | 12 | C |
| 1101 | 13 | D |
| 1110 | 14 | E |
| 1111 | 15 | F |
| 10000 | 16 | 10 |
| 10001 | 17 | 11 |
| 10010 | 18 | 12 |
| 10011 | 19 | 13 |
|_________|__________|______________|
Pour passer d'une base à l'autre, nous allons toujours revenir à la base décimale :
Lorsque nous voulons passer de la base 2 à la base 16, on va faire base 2 => base 10 =>
base 16
Conversion de la base 10 en une autre base X :
----------------------------------------------
Méthode des divisions successives:
----------------------------------
Il faut diviser successivement le nombre à convertir par la base X puis noter le reste.
Ensuite diviser le quotient par la base X puis noter le reste. Répéter ces opérations
jusqu'a 0. Ensuite, pour obtenir le nombre dans la base X, il faut lire les restes de la
dernière division à la première:
Exemple:
--------
(LSB = Least significant bit soit bit le moins significatif, bit le plus à droite)
(MSB = Most significant bit soit bit le plus significatif, bit le plus à gauche, appelé bit de poids fort)
Nous allons convertir 142 en binaire (base 2) :
Pour la base 2, si le quotient est rationnel, on a un reste de 0 sinon on a un reste de 1
142/2 = 71 donc 0 (LSB)
71/2 = 35.5 donc 1
35/2 = 17.5 donc 1
17/2 = 8.5 donc 1
8/2 = 4 donc 0
4/2 = 2 donc 0
2/2 = 1 donc 0
2/1 = 0.5 donc 1 (MSB)
Cela donne 142 en base 10 = 10001110 en base 2.
Convertissons maintenant 1478 en hexadécimal (base 16) :
1478/16 = 96 reste 6
92/16 = 5 reste 12
5/16 = 0 reste 5
Or 12 en base 10 = C en base 16
donc on a 1478 en base 10 = 5C6 en base 16.
Conversion d'une base X en base 10 :
------------------------------------
Pour passer d'une base X en base 10, il faut multiplier le nombre chiffre à chiffre par
la base X à la puissance du poids du chiffre, chaque résultat sera additionné, le tout à l'envers, ce sera plus simple à travers un exemple:
Nous avons 11010 en base 2 et nous le voulons en base 10, nous allons donc prendre le premier chiffre (0) que nous multiplions par 2^0 car c'est le premier. Ensuite nous allons ajouter 1*2^1 + 0*2^2 + 1*2^3 + 1*2^4 = 0 + 2 + 0 + 8 + 16 = 26. Donc 11010 en base 2 nous donne 26 en base 10.
Autres exemples:
----------------
On veut convertir C1DF5 qui est en base 16 vers la base 10:
5*16^0 + 15*16^1 + 13*16^2 + 1*16^3 + 12*16^4 =
5 + 240 + 3328 + 4096 + 786432 = 794101
On veut maintenant convertir 45601 qui est en base 8 vers la base 10:
1*8^0 + 0*8^1 + 6*8^2 + 5*8^3 + 4*8^4 =
1 + 0 + 384 + 2560 + 16384 = 19329
Les nombres signés :
--------------------
Un nombre peut se représenter sous sa forme binaire, décimale ou hexadécimale.
Bien souvent, c'est la représentation hexadécimale qui est utilisée car le nombre est codé sur une longueur 8 symboles ("8 chiffres").
Voici un nombre entier positif de type long (32 bits)
10001110010110100001110011111010
et sa représentation en décimal 2388270330
et en hexadécimal 8E5A1CFA
On voit l'avantage du codage hexadécimal.
Pour un nombre de 32 bits, il y a 2^32 possibilités de valeurs allant de
00000000000000000000000000000000 à 11111111111111111111111111111111
Pour des nombres positifs, ces valeurs vont de
00000000000000000000000000000000 --> $00000000 --> 0 en décimal
à
11111111111111111111111111111111 --> $FFFFFFFF --> 4294967295 en décimal
Nombres signés : Représentation d'un nombre négatif :
-----------------------------------------------------
Le résonnement suivant sur 32 bits est valable sur 16, 8 bits etc.
La solution pour stocker le signe est l'utilisation du bit b31 comme bit de signe.
B31 à 0 c'est un positif et à 1 c'est un nombre négatif.
Pour trouver un nombre négatif à partir du nombre positif, on inverse bit à bit et on ajoute 1
par exemple le nombre 20 codé sur 32 bits
00000000000000000000000000010100 --> +20
on inverse bit à bit
11111111111111111111111111101011
on ajoute 1
11111111111111111111111111101100 --> -20
Il s'agit du complément à deux qui est utilisé pour les calculs des entiers signés.
L'inversion simple bit à bit s'appelle le complément à un.
Pour résumer
11111111111111111111111111101011 est un nombre négatif
|
| bit de
| signe
|
01111111111111111111111111101011 est un nombre Positif
Le complément à deux d'un entier est la valeur positive qui permet d'obtenir 0 lorsque les deux valeurs sont additionnées.
Cette notion de nombre signé est très importante car en assembleur on effectue beaucoup de tests sur les valeurs des registres, mémoires, la pile etc.
Il existe une grande variété de tests, une partie servant pour les nombres non signés et une autre pour les nombres signés.
Purebasic n'utilise que des nombres signés. Si l'on écrit une librairie pour Purebasic, on peut utiliser les nombres signés ou non en fonction des besoins.
Un exemple simple pour expliquer ceci.
On a une liste chaînée ou une listview et on récupère le nombre d'éléments dans un registre et on compare à une valeur.
On peut très bien tester sur la base de nombres non signés car ces fonctions ne retournent jamais un nombre négatif. Il faut ne pas oublier quel type de nombre on manipule.
Le complément à deux fonctionne aussi pour trouver un nombre positif en partant d'un négatif.
Prenons la valeur décimale 1 codée sur 8 bits
00000001
11111110 on inverse bit à bit
+00000001 on ajoute 1
----------
11111111 --> -1
On part de ce nombre -1
11111111 --> -1
00000000 on inverse bit à bit
+00000001 on ajoute 1
----------
00000001 --> 1
Pour trouver la valeur d'un nombre décimal négatif en binaire, on fait comme ceci :
Par exemple -37
En binaire 37 s'écrit 00100101
On inverse 11011010
on ajoute 1 --> 11011010
11011010 vaut donc -37
Maintenant, pour nous faciliter la vie, vous allez écrire en PureBasic un convertisseur décimal/binaire/hexadécimal prenant en compte les nombres signés ou non.
Avec une belle Interface et tout et tout (merci aux courageux).
Les intervalles des nombres signés :
------------------------------------
Pour un nombre de 8 bits (un octet = un byte), on ne va utiliser que 7 bits pour coder la valeur absolue du nombre puisque le dernier bit (poids fort) ne sera qu'un indicateur de signe.
Ceci est vrai quelque soit le nombre de bits.
Byte (8 bits) -128 à +127
Word (16 bits -32768 à +32767
Dword (32 bits) -2147483648 à +2147483647
Qword (64 bits) -9223372036854775808 à +9223372036854775807
On calcule les plages comme ceci
Exemple pour 16 bits :
Partie négative = -(2^15) --> 15 bits sur les 16 pour la valeur absolue
Partie positive = (2^15)-1 --> on retire 1 car il faut bien que le 0 soit codé
Le cas du zéro :
----------------
00000000
11111111 on inverse bit à bit
+00000001 on ajoute 1 (pour le complément à deux)
----------
00000000 --> 0
En complément à deux, le bit de signe du 0 est toujours 0. 0 n'a pas de représentation -0.
L'intervalle des positifs a autant de nombres que l'intervalle des négatifs sauf que l'intervalle des positifs commence à 0 tandis que celui des négatifs commence à -1.
L'intervalle sur 16 bits va de -32768 à +32767 et non pas de -32768 à +32768
Voilà pour le troisième tut.
Merci à Oliv pour la partie de changement de base.
Prochain tut : Approche du fonctionnement d'un microprocesseur de la famille X86.
A+
Denis