Codage des caractères
La façon dont les ordinateurs parviennent à représenter un texte est indispensable à notre quotidien. Depuis les premiers temps de l’informatique, plusieurs méthodes concurrentes ont été développées avant que certaines ne s’imposent.
Bref historique
Le code binaire est né avant l’informatique. Ainsi le brevet du code Morse a été déposé en 1840. Puis le code Baudot, développé en 1874, a connu des améliorations successives, notamment pour la télégraphie.
Ensuite sont apparus les ordinateurs, conçus pour calculer. Plus tard, un nouveau besoin est né. Celui d’encoder non seulement des nombres mais aussi des caractères. Plusieurs solutions ont vu le jour, incompatibles les unes avec les autres.
Avec l’avènement des premiers ordinateurs personnels dans les années 70, il est devenu nécessaire d’établir une norme pour représenter le texte de manière cohérente.
Mais déjà, en 1963, l’ANSI (American National Standard Institute) avait développé un système qui correspondait aux besoins de l’époque : le codage ASCII.
ASCII
Le codage ASCII (American Standard Code for Information Interchange) repose sur un principe très simple : chaque caractère est associé à un code numérique unique. Plus précisément à un octet. C’est une limite forte puisque seulement 128 caractères peuvent être traduits (soit \(2^7\)) le dernier bit de chaque octet étant réservé au contrôle de la transmission). Ceux-ci sont les lettres majuscules et minuscules, les signes de ponctuation, les opérateurs arithmétiques, les chiffres (soit 95 caractères imprimables) … Les octets restants sont réservés à d’autres instructions (signal sonore, fin de texte…).
Un encodage aussi limité ne permet de traduire que l’anglais puisque même les voyelles accentuées ne peuvent être prises en compte.
La table des codes ASCII se trouve notamment ici :
Le codage ASCII est encore utilisé aujourd’hui, c'est pourquoi les caractères accentués sont parfois interdits (adresses mail, noms de domaines…).
Avec Python, vous pouvez traduire un caractère avec la fonction ord. La sortie est en base décimale. Ajouter la fonction bin comme ceci pour obtenir un résultat en binaire :
bin(ord('a'))
On obtient :
'0b1100001'
Le a minuscule correspond au code 01100001 (ne pas tenir compte de 0b, à remplacer par un ou plusieurs zéros).
Voir l'exercice sur ASCII.
ISO 8859
En codant les caractères sur huit bits au lieu de sept, l’ISO (Organisation Internationale de Normalisation) a doublé les possibilités de l’ASCII. Mais cela reste très insuffisant, même pour les seules langues qui utilisent sur l’alphabet latin.
La norme ISO 8859 repose sur seize tables, chacune étant adaptée à une zone géographique. La première est celle de l’Europe occidentale. Elle comprend des caractères typiquement français (avec accents circonflexes), allemand (ß), etc. Quelques langues non européennes ne nécessitent pas davantage de caractères et sont donc codées avec cette même norme ISO 8859-1 (indonésien, wolof…). En tout, l’alphabet latin occupe dix tables. Par exemple, l’ISO 8859-2 est celle de l’Europe centrale et de l’est (polonais, tchèque, hongrois…).
Les tables non latines comprennent les alphabets cyrilique, arabe, grec, hébreu et thaï.
L’inconvénient de ce système est qu’il n’est pas possible de mélanger des caractères d’alphabets différents dans un même texte.
En l’absence de caractères spéciaux, l’emploi d’ISO 8859-1 revient à coder en ASCII. Soit par exemple le mot Bonjour.
B est représenté par le code ASCII 66, soit en binaire 01000010 (essayez alt + 66 avec votre clavier), o est la traduction du code ASCII 111, soit en binaire 01101111, et ainsi de suite. Finalement, en ISO 8859 comme en ASCII Bonjour est codé :
01000010 01101111 01101110 01101010 01101111 01110101 01110010
En revanche, le codage de ê n’est pas possible en ASCII puisque l'accent circonflexe n'est pas géré. Un exemplaire de la table 8859-1 se trouve ici (pour les caractères indisponibles en ASCII) :
https://fr.manpages.org/iso_8859-1/7
Il apparaît que ê a pour code décimal 234 (il se situe bien entre 128 et 257, comme vous l’aviez deviné). Sa forme binaire est 11101010. Vous pouvez le vérifier avec Python, à partir du script indiqué plus haut.
Unicode
Comme son nom le laisse supposer, Unicode ne repose pas sur plusieurs tables.
À partir de 1991, l’ISO a défini une nouvelle norme, probablement définitive : l’ISO 10646, qui s’appuie sur un jeu universel de caractères (UCS, pour Universal Character Set).
Chaque caractère, de n’importe quel alphabet et écriture, est associé à un point de code qui est un nombre entier. Le caractère peut être une lettre, un idéogramme chinois, une émoticône, etc.
Pour noter un point de code, on fait suivre U+ par au moins quatre chiffres en notation hexadécimale. Soit la possibilité de coder un caractère sur quatre octets. Là encore, les 128 premiers termes correspondent au code ASCII.
Mais la plupart du temps, l’emploi de quatre octets par caractère relève du gaspillage puisque pour l’alphabet latin, un seul suffit presque toujours.
D’où l’idée de créer plusieurs versions d’Unicode en fonction du nombre d’octets nécessaires.
Avec UTF-8, le point de code s’appuie sur huit bits au minimum. Mais le principe est différent de celui d’ISO 8859. Les premiers bits indiquent comment codent les suivants. Supposons que le point de code commence par zéro. Là c’est simple, on retrouve l’ASCII. Sinon, le nombre de 1 placés au début déterminent le nombre d’octets nécessaires pour coder le caractère. Ainsi, un octet suffit s’il commence par 10, deux s’il commence par 110, etc.
Par exemple, ê est codé sur deux octets. Son point de code est U+00EA (les caractères codés sur deux octets se situent entre U+0080 et U+07FF). Le premier commence donc par 110. En l’occurrence, il s’agit de 11000011 10101010.
UTF-8 est le plus utilisé sur le web. D’ailleurs on trouve très souvent la balise de métadonnées <meta charSet="utf-8"/> en tête du code HTML des pages web (faites un clic droit puis Code source de la page si vous souhaitez visualiser le code de cette page). Voir l'exercice de codage UTF-8.
UTF-16 est un format sur seize bits minimum (jusqu’au point de code U+10FFFF) et UTF-32 représente tous les caractères sur 32 bits, ce qui nécessite un espace de stockage conséquent.
Nous n’entrerons pas dans les détails techniques. Précisons tout de même que des confusions peuvent survenir en UTF-8 et UTF-16 mais pas en UTF-32. Quant aux formules mathématiques, elles ne s'écrivent pas souvent de façon linéaire (fractions, limites, sommes...) ; malgré les capacités d'Unicode il faut employer des systèmes de composition particuliers (éditeur de formules de Word, LaTeX...).