Les opérations arithmétiques
L'addition
Nous allons voir ici comment additionner deux nombres binaires. En fait ca marche exactement comme avec les nombres décimaux. Prenons un exemple:
01011010 64 + 16 + 8 + 2 = 90
+ 00011101 16 + 8 + 4 + 1 = 29
-----------
01110111 64 + 32 + 16 + 4 + 2 + 1 = 119
Procédons par étape (de droite à gauche, comme pour une addition "normale"):
0+1 = 1
1+0 = 1
0+1 = 1
1+1 = 0, je retiens 1 (On dépasse le chiffre
maximum de la base, on pose donc une retenue)
1+1+1 de retenue = 1, je retiens 1
0+0+1 de retenue = 1
1+0 = 1
0+0 = 0
La soustraction
On se basera sur le fait que 3 + 4 = 3 + (-4). Une soustraction revient à additionner un nombre négatif. Se référer donc au chapitre sur les nombres négatifs. (Ce chapitre se situe après celui ci car il me faut les opérations pour pouvoir expliquer les nombres négatifs).
La multiplication
Pour multiplier un nombre par 2^n, il suffit de le décaler de n rangs vers la gauche. Tout ce qui sort de la gauche est supprimé, et on comble à droite avec des 0. Logique en somme, vu que pour passer d'un nombre binaire en décimal on fait:
nombre = bit0 * 20 + bit1 * 21 + .... + bitn*2max
Avec bit0 la valeur du bit0, bit1 la valeur du bit1... et max le rang du bit à 1 du poids le plus fort (le bit le plus à gauche différent de 0). Si on décale tout les bits de n rangs, ca devient:
nombremultiplié = bit0*2(0+n) + bit1*2(1+n) + ....+ bitn*2(max+n)
= 2n * (bit0 * 20 + bit1 * 21 + .... + bitn*2max)
= 2n * nombre
Le fait de tout décaler modifiera partout l'exposant du 2, que l'on peut ensuite passer en facteur. Plusieurs questions devraient vous venir à l'esprit:
- Que se passe-t'il si j'ai un octet, contenant par exemple 115 (01110011), et que je veux le multiplier par 2? Bah y'a qu'a tester. Ca fera 11100110. Un nombre négatif (-26 -> cf chapitre sur les nombres négatifs). C'est normal. Avec un octet, le plus petit entier positif que l'on peut représenter est 0 (00000000). Le plus grand nombre positif est 01111111: 127. Or si je multiplie 115 par 2, je dépasse cette fameuse valeur. Donc à moins d'utiliser cet octet comme entier non signé, c'est à dire en négligeant le bit de signe, vous ne pourrez pas dépasser la valeur 127, sans quoi vous obtiendrez des résultats imprévisibles. C'est ca le buffer overflow, le fait d'essayer de rentrer un nombre dans un objet qui ne peux pas le contenir :).
- Et comment je fais si je veux multiplier par autre chose que 2? Bah... Tu te démerdes :) Mettons qu'on a un nombre A qu'on souhaite multiplier par 15. Aïe, c'est pas un multiple de 2 ca. On peut toutefois écrire 15 = 8+4+2+1.
A * 15 vaut donc A*(8+4+2+1) = A*8 + A*4 + A*2 + A.
Et ca on sait faire :)
La division
Bah, au lieu de décaler de n rangs vers la gauche pour multiplier par n, on décalera de n rangs vers la droite pour diviser par n. On ajoute des 0 à gauche pour compléter, et on éjecte tout par la droite. Mais attention: vous n'obtiendrez qu'un résultat tronqué. Supponsons que j'ai l'octet suivant : 00010010 et que je veuille le diviser par 2^3 (8d). Il faudrait que je décale tout de 3 rangs vers la droite, mais mince, y'a le 1 de la position 1 qui se barre. Ce 1 en gros, bah c'est le reste de la division :).