Un ordinateur ne connaît que deux états : courant ou pas, aimanté ou non, 0 ou 1.
Toute donnée (nombre, texte, image, son) doit donc être traduite en suites de bits.
Ce chapitre commence par les entiers : comment les écrire en base 2 (binaire) et en base 16 (hexadécimal), combien de bits il faut pour les écrire, et comment représenter les entiers relatifs grâce au complément à 2.
1. Écrire un entier dans une base
1.1 Le principe positionnel
En base 10, le nombre 4072 signifie 4×103+0×102+7×101+2×100.
Chaque chiffre est multiplié par une puissance de la base, qui dépend de sa position.
Base
Nom
Chiffres
2
binaire
0 et 1
10
décimal
0 à 9
16
hexadécimal
0 à 9, puis A, B, C, D, E, F pour 10 à 15
1.2 De la base 2 à la base 10
On additionne les puissances de 2 qui correspondent aux bits à 1.
101101012=128+32+16+4+1=181.
defdecimal(s):
n = 0# à toireturn n
Correction · Pourquoi
n = 2 * n + int(c) ?
Lire un bit de plus, c'est décaler tout ce qu'on a déjà lu d'un rang vers la gauche, donc le multiplier par 2, puis ajouter le nouveau bit.
Une autre solution, plus proche de la définition, parcourt les index et ajoute 2 ** (len(s) - 1 - i) quand s[i] vaut "1".
1.3 De la base 10 à la base 2 : les divisions successives
Division
Quotient
Reste
45=2×22+1
22
1
22=2×11+0
11
0
11=2×5+1
5
1
5=2×2+1
2
1
2=2×1+0
1
0
1=2×0+1
0
1
Donc 45=1011012.
Vérification : 32+8+4+1=45.
Le programme suit exactement la méthode des divisions, et affiche chaque étape.
defbinaire(n):
"""Écriture binaire de l'entier positif n, sous forme de chaîne."""if n == 0:
return"0"
s = ""while n > 0:
print(n, "= 2 x", n // 2, "+", n % 2)
s = str(n % 2) + s # le reste se place devant
n = n // 2return s
print(binaire(45))
Python possède aussi des fonctions toutes faites.
>>> bin(45)
'0b101101'>>> int("101101", 2)
45
Le préfixe 0b signale une écriture binaire.
1.4 La base 16 : l'hexadécimal
101101012→10112=11=B,01012=5⇒181=B516.
Binaire
Hexa
Binaire
Hexa
Binaire
Hexa
Binaire
Hexa
0000
0
0100
4
1000
8
1100
C
0001
1
0101
5
1001
9
1101
D
0010
2
0110
6
1010
A
1110
E
0011
3
0111
7
1011
B
1111
F
L'hexadécimal sert à écrire de façon compacte des contenus binaires : couleurs, adresses mémoire, adresses MAC, codes Unicode.
Un octet (byte) vaut 8 bits.
Les préfixes : 1 ko =103 octets, 1 Mo =106, 1 Go =109.
À ne pas confondre avec 1 Kio =210=1024 octets.
defnb_bits(n):
# à toireturn0
2.2 Somme et produit
Par exemple, 255+255=510<512=29, et 255×255=65025<65536=216.
Python, lui, manipule des entiers de taille arbitraire : il n'y a pas de débordement, la mémoire s'adapte. Ce n'est pas le cas de la plupart des langages (C, Java), où un int occupe 32 bits.
# Python n'a pas de limite de tailleprint(2 ** 100)
# On simule un registre de 8 bits : on ne garde que le reste modulo 256print((200 + 100) % 256)
2.3 Addition binaire
On additionne colonne par colonne, avec retenue, comme en base 10.
Pour représenter des entiers négatifs, l'idée naïve est de réserver un bit de signe (0 pour +, 1 pour −), suivi de la valeur absolue.
Elle a deux défauts : elle donne deux zéros (+0 et −0), et elle complique l'addition.
Les processeurs utilisent une autre représentation : le complément à 2.
3.2 Le principe
Sur 8 bits, les poids sont donc −128,64,32,16,8,4,2,1.
001001012=32+4+1=37
110110112=−128+64+16+8+2+1=−37
3.3 Calculer l'opposé
37=001001012inversion110110102+1110110112=−37.
La même opération redonne 37 à partir de −37.
defcomplement_a_2(x, n):
"""Motif sur n bits de l'entier relatif x (positif ou négatif)."""
motif = bin(x % 2 ** n)[2:] # x % 2**n vaut 2**n - |x| si x est négatifreturn"0" * (n - len(motif)) + motif
print(complement_a_2(37, 8))
print(complement_a_2(-37, 8))
print(complement_a_2(-202, 16))
Essaie les valeurs extrêmes sur 8 bits : 127, −128, puis −1. Que donne 128, qui n'est pas représentable ?
3.4 Un même motif, deux lectures
Le motif 110110112 vaut 219 si on le lit comme un entier non signé, et −37 si on le lit comme un entier signé.
defvaleur_signee(motif):
n = int(motif, 2)
# à toi : que faire si le bit de poids fort vaut 1 ?return n
4. Exemple résolu pas à pas
Correction · Question a
202=2×101+0 ; 101=2×50+1 ; 50=2×25+0 ; 25=2×12+1. 12=2×6+0 ; 6=2×3+0 ; 3=2×1+1 ; 1=2×0+1.
Restes lus de bas en haut : 202=110010102.
Vérification : 128+64+8+2=202.
Quartets : 1100=C et 1010=A, donc 202=CA16.
Correction · Question b
128≤202<256=28 : il faut 8 bits.
Somme : 404<512=29, donc 9 bits.
Produit : 40804<65536=216, donc 16 bits, soit 2×8.
Correction · Question c
Sur 16 bits, 202=00000000110010102.
Inversion : 11111111001101012.
Plus 1 : 11111111001101102.
Vérification : 65536−202=65334=FF3616.
Correction · Question d
Non signé : 128+64+32+16=240.
Signé : −128+64+32+16=−16.
Vérification : 240−256=−16.