• Aucun résultat trouvé

2.1.1

Écriture dans une base

Rappels sur la base 10. Considérons un nombre entier strictement positif, par exemple N = 432. Alors, N s’écrit N = 4 × 102+ 3 × 101+ 2 × 100. Cette écriture se généralise à tout entier, par le théorème suivant :

Théorème 2.1. Soit N un entier strictement positif, alors il existe n strictement positif et des entiers a0, . . . , an−1

tels que :

— pour tout i dans {0, . . . , n − 1}, ai appartient à {0, . . . , 9}, ce qu’on note (a0, . . . , an−1) ∈ [[0, 9]]n,

— an−16= 0,

et N = an−1× 10n−1+ an−2× 10n−2+ · · · + a0× 100 =Pn−1k=0ak× 10k. De plus, l’entier n et les entiers (ai) sont

uniques.

Généralisation à une base quelconque. L’écriture précédente se généralise aisément à une base quelconque : Théorème 2.2. Soit N un entier strictement positif, et b un entier positif supérieur ou égal à 2. Alors il existe n strictement positif et des entiers a0, . . . , an−1 tels que :

— pour tout i dans {0, . . . , n − 1}, ai appartient à {0, . . . , b − 1}, ce qu’on note (a0, . . . , an−1) ∈ [[0, b − 1]]n,

— an−16= 0,

et N = an−1× bn−1+ an−2× bn−2+ · · · + a0× b0=Pn−1k=0ak× bk. De plus, l’entier n et les entiers (ai) sont uniques.

On note un tel entier N dans la base b comme suit : N = an−1an−2· · · a1a0b. On va prouver ce théorème dans la

suite. Voyons d’abord quelques exemples, par exemple l’écriture de 17 dans toutes les bases entre 2 et 9 : 17 = 1 × 24+ 0 × 23+ 0 × 22+ 0 × 21+ 1 × 20 = 100012 = 1 × 32+ 2 × 31+ 2 × 20 = 1223 = 1 × 42+ 0 × 41+ 1 × 20 = 1014 = 3 × 51+ 2 × 30 = 325 = 2 × 61+ 5 × 60 = 256 = 2 × 71+ 3 × 70 = 237 = 2 × 81+ 1 × 80 = 218 = 1 × 91+ 8 × 90 = 189

Généralisation à des bases supérieures à 10. Hexadécimal. Pour représenter des nombres dans une base supérieure à 10, il est nécessaire d’introduire de nouveaux symboles pour exprimer les chiffres entre 10 et b − 1. En particulier, un exemple important en informatique est la base 16, appelée hexadécimale. Pour représenter les chiffres manquants, on utilise les lettres de A à F :

lettre A B C D E F

2.1. REPRÉSENTATION DES ENTIERS NATURELS Lycée Masséna

Avant de passer à la preuve du théorème 2.2, rappelons un résultat essentiel d’arithmétique : l’existence et l’unicité du reste dans une division euclidienne.

Théorème 2.3. Soit N et M deux entiers, avec M > 0. Alors il existe deux entiers q et r tels que : — N = qM + r,

— 0 ≤ r ≤ M − 1.

De plus, le couple (q, r) est unique.

Démonstration. L’ensemble E = {a ∈ Z | N − M a ≥ 0} est un sous-ensemble de Z. Il est non vide car tout entier inférieur à MN est dans E. Il est de plus borné supérieurement car tout entier strictement supérieur à MN n’est pas dans E. Ainsi, E possède un plus grand élément, qu’on note q. Posons alors r = N − M q ≥ 0. Si r était supérieur ou égal à M , alors (q + 1) serait dans E ce qui est absurde. Ainsi l’existence du couple (q, r) est démontrée. Pour l’unicité, considérons un autre couple (q0, r0) satisfaisant les mêmes hypothèses. On a alors M (q − q0) = r0 − r. Or

−(M − 1) ≤ r0− r ≤ M − 1, donc r0− r est un multiple de M strictement supérieur à −M et strictement inférieur à M , donc nul. On en déduit l’unicité de r, puis de q.

Preuve du théorème 2.2. On montre par récurrence l’existence et l’unicité d’une telle écriture. Fixons b ≥ 2, et pour N ≥ 1, posons P (N ) la propriété « N admet une écriture comme dans le théorème, et elle est unique ».

Initialisation : P (1), . . . , P (b − 1) sont vraies car pour N un des entiers parmi 1, . . . , b − 1, l’écriture N = Nb convient. De plus, si N = an−1an−2· · · a1a0b est une autre écriture, comme an−1> 0, nécessairement n = 1 car N est

strictement inférieur à b. Ainsi, N = Nb est la seule écriture convenable.

Hérédité : Soit N ≥ b, et supposons P (M ) pour tout entier M ∈ [[1, N − 1]]. Soit (q, r) le quotient et le reste dans la division euclidienne de N par b. Puisque N ≥ b, q est un entier strictement positif, inférieur strictement à N . On peut donc lui appliquer l’hypothèse de récurrence : il existe un entier p ≥ 1 tel que q s’écrivecp−1· · · c0b, avec ci∈ [[0, b − 1]]

et cp−16= 0. Alors, en posant n = p + 1, N = bq + r = b × p−1 X k=0 cibi ! + r = n−1 X k=1 ci−1bi ! + r = cn−2cn−3· · · c0rb

on voit que le n-uplet (an−1, . . . , a0) = (cn−2, . . . , c0, r) vérifie les conditions du théorème 2.2. De plus cette écriture

est unique : le dernier chiffre de N est nécessairement le reste de la division euclidienne de N par b, soit r. Les autres chiffres sont donnés par l’écriture de q, qui est unique par récurrence. Ainsi, par principe de récurrence, P (N ) est vraie.

Conclusion : P (N ) est vraie pour tout N ≥ 1 : l’existence et l’unicité sont démontrées.

Même si la preuve est un peu rébarbative, son application donne immédiatement un algorithme de changement de base, qu’on va voir dans la sous-section suivante. Avant ça, un petit point culture.

Histoire. Voici une petite présentation non exhaustive des différentes bases ayant été utilisées. Aujourd’hui, on (l’hu- manité) utilise la base 101. Ça n’a pas toujours été le cas : les égyptiens, les mayas, les babyloniens, mésopotamiens et d’autres ont utilisé les bases 20, 24 et 60. Les mésopotamiens n’utilisaient cependant pas 60 symboles différents : chaque « chiffre » était lui même codé avec un certain nombre de chevrons (chacun comptant pour 10) et de clous (chacun comptant pour une unité). En informatique2, la base 2 (binaire) apparaît naturellement : le 1 et le 0 corres-

pondent à une tension positive (supérieure à un certain seuil) ou une absence de tension (inférieure à un ce seuil) en un point d’un circuit électrique. Comme les écritures en binaire sont plutôt longues (on a vu qu’il fallait 5 chiffres pour représenter 17...), l’idée de raccourcir les écritures en utilisant des bases de la forme 2k a mené à l’hexadécimal, et plus

marginalement à l’octal (base 8). On verra qu’il est très facile de passer du binaire à l’hexadécimal (ou à l’octal) et réciproquement.

2.1.2

Changement de base

L’entier 1345 (en base 10), s’écrit 101010000012 en binaire et 54116 en hexadécimal. Pour pouvoir passer d’une base à une autre, il est nécessaire de savoir calculer dans la base de départ, ou bien dans la base d’arrivée. On va voir deux algorithmes correspondant à ces deux situations. On va également voir qu’il est facile de passer du binaire à l’hexadécimal, et réciproquement.

1. Probablement parce que les humains ont 10 doigts...

Si l’on sait calculer dans la base de départ. Dans ce qui suit, vous pouvez considérer que la base de départ est la base 10 : il nous faut simplement une base dans laquelle on sait faire une division euclidienne. On ne fera pas explicitement mention de cette base. L’algorithme 2.4 reprend l’idée de la preuve du théorème 2.2.

Algorithme 2.4 : Écriture depuis une base où on sait calculer Entrées : Un entier N > 0 et un entier b ≥ 2.

Sortie : L’écriture de N dans la base b. i ← 0;

M ← N ;

tant que M 6= 0 faire

(q, r) ← quotient et reste de la division euclidienne de M par b; ai← r;

M ← q; i ← i + 1;

retourner (ai−1, ai−2, . . . , a0)

En d’autres termes, on effectue des divisions euclidiennes tant que l’on ne tombe pas sur un quotient nul. La suite des restes fournit les chiffres de l’écriture de N dans la base b, du moins significatif au plus significatif (c’est-à-dire dans l’ordre inverse).

On a utilisé ici une boucle conditonnelle « Tant que », qui correspond en Python à une boucle while. Tant que la condition est vérifiée (ici M 6= 0), on exécute le corps de la boucle. Reprenons l’exemple du nombre 1345 que l’on veut convertir en hexadécimal. On effectue les divisions euclidiennes successives :

1345 = 16 × 84 + 1 84 = 16 × 5 + 4

5 = 16 × 0 + 5

Comme le dernier quotient est zéro, on s’arrête. La suite des restes successifs est 1, 4, 5, que l’on inverse. On obtient bien 1345 = 54116.

En Python, on stocke la suite des restes dans une liste. À la fin de l’algorithme, on inverse la liste et on la renvoie. Cela donne le code suivant :

def base10ab(N,b): L=[] #une liste vide M=N

while M!=0:

r=M%b #reste dans la division euclidienne M=M//b #quotient dans la division euclidienne L.append(r) #ajouter un élément à la fin d'une liste L.reverse() #on retourne la liste

return L >>> base10ab(17,2) [1, 0, 0, 0, 1] >>> base10ab(666,3) [2, 2, 0, 2, 0, 0] >>> base10ab(1345,16) [5, 4, 1]

Remarque : en pratique, il est très courant de représenter un nombre dans une base b par la donnée de ses chiffres du moins significatif au plus significatif : par exemple 1345 = 54116 peut se représenter en hexadécimal par la liste [1, 4, 5]. Cette représentation est assez pratique, car à une liste de chiffres [a_0, a_1, ..., a_p] est associée le nombre Pp

k=0akbk dans la base b. On appelle les deux représentations possibles big-endian (les chiffres les plus

significatifs en premier, on commence par « le gros bout ») et little endian3 (on commence par les moins significatifs,

soit le « petit bout »). L’algorithme précédent donne la représentation big endian, pour obtenir la représentation en little endian, il suffit de ne pas inverser la liste à la fin de l’algorithme. En interne sur un ordinateur, la représentation utilisée (l’« endianness ») dépend du système d’exploitation. Les deux sont utilisées, mais la représentation « little endian » est la plus répandue.

Si l’on sait calculer dans la base d’arrivée. Ici, on suppose que l’on sait faire les opérations + et × dans la base d’arrivée, que l’on pourra voir comme la base 10. Comment évaluer N = an−1· · · a0b dans cette base ? À partir

de l’écriture N =Pn−1

k=0akb

k, on voit qu’il suffit d’évaluer les puissances de b (jusqu’à bn−1) dans la base d’arrivée, de

multiplier bkpar a

ket de sommer. En supposant que 1 et b sont donnés sans calcul, cela nous fait 2n−3 multiplications :

3. Les termes big endian et little endian ont été popularisés par Dany-Cohen, en référence aux Voyages de Gulliver, le roman de Jonathan Swift où il est question d’un décret visant à décider par quel bout on doit commencer à manger un œuf à la coque, le gros ou le petit.

2.1. REPRÉSENTATION DES ENTIERS NATURELS Lycée Masséna

n − 2 pour calculer les bk et n − 1 pour multiplier chaque couple (a

k,bk), la multiplication a0× 1 étant gratuite. On

va voir un algorithme classique qui requiert environ moitié moins de multiplications : l’algorithme de Hörner. Celui-ci repose entièrement sur l’identité suivante :

N =

n−1

X

k=0

akbk= a0+ b × (a1+ b × (a2+ b × (a3+ · · · + b × an−1)) · · · )

Algorithme 2.5 : Écriture dans une base dans laquelle on sait calculer

Entrées : Un entier b ≥ 2 et un entier N donné par la liste de ses chiffres dans la base b : N = an−1· · · a0b

Sortie : L’évaluation de N dans la base ambiante M ← 0;

pour chaque i allant de n − 1 à 0 par pas de −1 faire M ← b × M + ai;

retourner M

Comme on le voit, l’algorithme 2.5 est particulièrement court. On a utilisé ici une boucle inconditionnelle : i prend successivement les valeurs n − 1, n − 2, . . . , 0. La structure en Python correspondante estfor. Prenons un exemple : convertissons N = 6ABC16en base 10. Cela consiste à évaluer l’expression 12 + 16 × (11 + 16 × (10 + 16 × 6)). Allons-y :

N = 12 + 16 × (11 + 16 × (10 + 16 × 6)) = 12 + 16 × (11 + 16 × 106)

= 12 + 16 × 1707 N = 27324

Voici une fonction Python qui réalise l’algorithme de Hörner. On suppose queL est une liste contenant les entiers an−1, . . . , a0 dans cet ordre. Il suffit de parcourir la liste dans l’ordre croissant des indices.

def baseba10(L,b):

n=len(L) #longueur de la liste N=0

for i in range(n): #parcours de la liste N=b*N+L[i] return N >>> baseba10([1,0,0,0,1],2) 17 >>> baseba10([5,4,1],16) 1345 >>> baseba10([6,10,11,12],16) 27324

Un cas particulier : l’une des bases est une puissance de l’autre. On a dit plus haut qu’il était facile de passer du binaire à l’hexadécimal et réciproquement. En fait, c’est le cas si l’une des bases est b et l’autre b`, pour un

certain ` > 1.

Prenons tout de suite un exemple : N = 27324 s’écrit6ABC16 mais aussi 1101010101111002. Comme 16 = 24, il suffit d’écrire la correspondance entre les 16 chiffres hexadécimaux et les chaînes de 4 chiffres en binaire (complétés par des zéros à gauche). La correspondance est la suivante :

hexadécimal 0 1 2 3 4 5 6 7

binaire 0000 0001 0010 0011 0100 0101 0110 0111

hexadécimal 8 9 A B C D E F

binaire 1000 1001 1010 1011 1100 1101 1110 1111

Ainsi, les 16 bits de l’écriture de 6ABC16en binaire sont bien donnés par les cases correspondant à 6, A, B et C dans ce tableau, en enlevant le 0 inutile à gauche. Réciproquement, pour passer de la base 2 à la base 16, on regroupe les bits par paquets de 4, en commençant par la droite, et en rajoutant éventuellement des zéros à la gauche du nombre, et on utilise le tableau. Par exemple, 1001012 s’écrit 2516car 01012 correspond à 516 et 00102 à 216.

Dans le cas général, il suffit d’établir une correspondance entre les paquets de ` chiffres dans la base b et les chiffres dans la base B = b`. En effet, soit N =Pn−1

k=0akbk un nombre exprimé dans la base b, avec ak∈ {0, . . . , b − 1}. Quite

à ajouter des chiffres nuls au début de la représentation en base b, on suppose que n est un multiple de `, il s’écrit donc n = ` × m. Alors : N = Pn−1 k=0akbk = Pm−1 i=0  P`−1 j=0aj+i` bj+i` 

(on découpe par paquets de ` chiffres) N = Pm−1

i=0 Bi

P`−1

Comme chaque aj+i`est entre 0 et b − 1 (ce sont les chiffres de N dans la base b), chaque somme Ai=P `−1 j=0aj+i`bj

est entre 0 etP`−1

j=0(b − 1)b

j = b`− 1 = B − 1. Autrement dit, les A

i sont des chiffres dans la base B = b`. On obtient

bien l’écriture de N dans la base B en regroupant les chiffres de N dans la base b par paquets de ` à partir de la droite, et en faisant une transcription à l’aide d’une table de la forme :

base b base B = b` 0 · · · 00b 0 0 · · · 01b 1 .. . ... 10 · · · 0b b`−1 .. . ... (b − 1) · · · (b − 1)(b − 1)b b`− 1 = B − 1

Le premier chiffre Am−1 est bien non nul, pour peu qu’on ait rajouté tout juste le nombre de zéros à gauche (éven-

tuellement aucun) nécessaire pour que le nombre de chiffres de N dans la base b devienne un multiple de `.

Réciproquement, si on part d’un nombre dans la base B, il suffit de faire le processus inverse pour retrouver un nombre dans la base b, quite à supprimer les chiffres nuls à gauche obtenus si le premier chiffre de N dans la base B est strictement inférieur à b`−1.