Skip to main content Informatique en prépa - Lycée Malherbe 

11- Représentation des nombres

Dans un ordinateur, tout est stocké sous forme de bits (0 ou 1). Comment représenter des nombres entiers, positifs ou négatifs, ou des nombres à virgule ?

I. Entiers positifs

a) Écriture en base 2

Tout entier naturel s'écrit de manière unique en base 2 :

Par exemple, , qui s'écrit en base 2.

Python

Loading editor...

print(bin(13))          # l'écriture en base 2, précédée de 0b
print(int("1101", 2))   # et dans l'autre sens

b) Mots de taille fixe

Le processeur manipule des mots de taille fixe : 8, 16, 32 ou 64 bits. Sur un mot de bits, on peut représenter les entiers de à .

Taille du motPlus grand entier
8 bits (un octet)
16 bits
32 bits
64 bits

Que se passe-t-il si un calcul dépasse cette valeur ? Le résultat est calculé modulo : on parle de dépassement de capacité. Par exemple, sur 8 bits, donne .

Python

Loading editor...

def addition_8_bits(a, b):
    """Simule une addition sur un mot de 8 bits."""
    return (a + b) % 2 ** 8

print(addition_8_bits(200, 50))
print(addition_8_bits(200, 100))

II. Entiers signés : le complément à deux

Pour représenter des entiers négatifs sur bits, on utilise le complément à deux : on représente l'entier par l'écriture en base 2 de :

Par exemple, sur 8 bits, on représente les entiers de à , et est représenté par , soit .

Python

Loading editor...

def complement_a_deux(x, n):
    """Renvoie la chaîne des n bits représentant x en complément à deux."""
    assert -2 ** (n - 1) <= x < 2 ** (n - 1)
    if x < 0:
        x += 2 ** n
    return bin(x)[2:].zfill(n)   # zfill complète avec des 0 à gauche

for x in [5, 1, 0, -1, -5, 127, -128]:
    print(x, "->", complement_a_deux(x, 8))
Propriétés du complément à deux

  • Le bit de poids fort (le plus à gauche) vaut 1 exactement pour les nombres négatifs.
  • Pour obtenir la représentation de , on inverse tous les bits de , puis on ajoute 1.
  • L'addition se fait exactement comme pour les entiers positifs (modulo ) : le processeur n'a pas besoin d'un circuit spécial pour les négatifs.

Par exemple, sur 8 bits : se calcule , et en ne gardant que 8 bits, on obtient .

III. Les entiers de Python

En Python, les entiers ne sont pas limités à 64 bits : ce sont des entiers multi-précision, dont la taille augmente selon les besoins.

Python

Loading editor...

print(2 ** 64)
print(2 ** 200)
print(len(str(2 ** 10000)), "chiffres")

C'est très pratique, mais cela a un coût : les opérations sur de grands entiers ne se font plus en temps constant. Par exemple, une addition de deux entiers de chiffres prend un temps proportionnel à : il devient difficile d'évaluer la complexité d'un programme qui manipule de très grands entiers.

Dans la plupart des autres langages (C, OCaml...), les entiers sont de taille fixe, et les dépassements de capacité ne provoquent pas d'erreur (ou plutôt, provoquent des erreurs invisibles) !

IV. Nombres à virgule : les flottants

a) Réels, décimaux, flottants

On représente donc les nombres à virgule de manière approchée, par des flottants.

b) Mantisse et exposant

Un flottant représente un nombre sous la forme :

où :

Comme la mantisse commence toujours par , ce n'est pas stocké. Le nombre ne peut donc pas s'écrire ainsi : il a une représentation spéciale (exposant et mantisse nuls).

Par exemple, : le signe est , la mantisse , l'exposant .

En Python, les flottants sont stockés sur 64 bits : 1 bit de signe, 11 bits d'exposant, 52 bits de mantisse. On a donc environ 16 chiffres significatifs.

c) Conséquences sur les calculs

Les calculs sur les flottants sont arrondis à chaque opération :

Python

Loading editor...

print(0.1 + 0.2)
print(0.1 + 0.2 == 0.3)
print(1e16 + 1 - 1e16)

Il ne faut donc jamais tester l'égalité de deux flottants avec ==. On teste plutôt si leur différence est petite :

Python

Loading editor...

def presque_egaux(x, y, eps=1e-9):
    return abs(x - y) < eps

print(presque_egaux(0.1 + 0.2, 0.3))

Les erreurs d'arrondi peuvent aussi s'accumuler :

Python

Loading editor...

s = 0
for k in range(1000):
    s += 0.1
print(s)

Exercices

Exercice 1

Donnez l'écriture en base 2 de 42, puis la représentation de en complément à deux sur 8 bits.

, soit sur 8 bits. On inverse les bits : , puis on ajoute 1 : est représenté par (c'est-à-dire ).

Exercice 2

Écrire une fonction valeur(bits) qui prend une chaîne de bits (par exemple "11010110") et renvoie l'entier qu'elle représente en complément à deux.

Python

Loading editor...

def valeur(bits):
    n = len(bits)
    x = int(bits, 2)
    if bits[0] == "1":   # nombre négatif
        x -= 2 ** n
    return x
Exercice 3

Que renvoie 0.1 * 3 == 0.3 ? Pourquoi ? Écrire le test correctement.

Python

Loading editor...

False : n'est pas représentable exactement, et 0.1 * 3 vaut 0.30000000000000004. On écrit plutôt abs(0.1 * 3 - 0.3) < 1e-9.