7.1. Sur les codages de caractères#
Un ordinateur ne manipule que des nombres binaires, comme 1001, la question qui s’est assez rapidement posée est celle de la représentation des caractères.
2**(8 - 1)
128
On rappelle qu’on groupe de 8 bits forme un octet, qui est l’unité de base de la numération dans un ordinateur.
Rappel : un bit est un nombre binaire qui est soit 1 soit 0. C’est la plus petite unité non-divisible, mais ça n’est pas l’unité pratique (qui est l’octet)
Le calcul \(2^{8-1} = 128\) correspond au nombre de nombres représentables avec 7 bits. Le dernier bit devait correspondre à un bit de contrôle.
Les chercheurs en informatique et les industriels des années 60 ont établit une correspondance entre les nombres entre 0 et 127 et les caractères de l’alphabet. Cette table de correspondance, élaborée aux États-Unis, s’appelle la table ASCII.
La fonction chr()
permet d’obtenir le caractère associé à un nombre.
chr(65)
'A'
chr(95)
'_'
chr(0)
'\x00'
Représentons déjà les 8 premiers caractères.
def premiers_caractères_ascii():
r = ""
for i in range(16):
r = r + f"{chr(i):2}"
return r
premiers_caractères_ascii()
'\x00 \x01 \x02 \x03 \x04 \x05 \x06 \x07 \x08 \t \n \x0b \x0c \r \x0e \x0f '
Ces 16 premiers caractères sont essentiellement des caractères de contrôle. Il servent à contrôler l’affichage (souvent des impressions dans les années 1960). En particulier, on peut noter :
\n
pour le retour à la ligne\r
pour le retour chariot (penser à une machine à écrire)\t
pour la tabulation (4 espaces, bien connue en Python)
def table_ascii():
l = []
for i in range(8):
r = ""
for j in range(15):
r = r + f"{chr(i*16 + j):3}"
l = l + [r]
return l
table_ascii()
['\x00 \x01 \x02 \x03 \x04 \x05 \x06 \x07 \x08 \t \n \x0b \x0c \r \x0e ',
'\x10 \x11 \x12 \x13 \x14 \x15 \x16 \x17 \x18 \x19 \x1a \x1b \x1c \x1d \x1e ',
' ! " # $ % & \' ( ) * + , - . ',
'0 1 2 3 4 5 6 7 8 9 : ; < = > ',
'@ A B C D E F G H I J K L M N ',
'P Q R S T U V W X Y Z [ \\ ] ^ ',
'` a b c d e f g h i j k l m n ',
'p q r s t u v w x y z { | } ~ ']
La table se complique lorsqu’on veut insérer d’autres caractères.
char = "é"
char.encode("iso8859-1")
b'\xe9'
chr(0xe9)
'é'
char.encode('utf-8')
b'\xc3\xa9'
b'\xe9'.decode('utf-8')
---------------------------------------------------------------------------
UnicodeDecodeError Traceback (most recent call last)
Cell In[13], line 1
----> 1 b'\xe9'.decode('utf-8')
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xe9 in position 0: unexpected end of data
b'\xc3\xa9'.decode('iso8859-15')
'é'
La table ASCII ne contenant pas tous les caractères de toutes les langues, celle-ci a été étendue, localement en fonction des besoins d’une langue ou d’une autre. Ainsi, on a eu
iso8859-1 pour le latin étendu (caractères accentués)
iso8859-8 pour le turc
mac pour les ordinateurs Mac des années 1980/1990
Depuis 1990, le consortium Unicode (qui réunit des industriels et des universitaires) a cherché à unifier les tables de caractères en proposant un système permettant de représenter des millions de graphèmes (unité d’affichage).
Ce sytème est organisé en plans, chacun étant une table de 0x0000
à 0xffff
0xffff
65535
Le plan 0 contient à lui tout seul 65535 caractères.
chr(0x1f353)
'🍓'
Même si un caractère existe dans Unicode, il peut ne pas être représenté si votre système d’exploitation de possède pas de glyphe dans la fonte (police) utilisée.
La fonction python qui permet, pour un caractère donné, d’afficher son point de code Unicode est ord()
.
ord('🍓')
127827
hex(ord('🍓'))
'0x1f353'
Cette fonction, comme la fonction chr()
fonctionne caractère par caractère. Si on veut travailler sur une chaine, il faut utiliser les méthodes .encode()
et .decode()
.
"Une fraise : 🍓".encode()
b'Une fraise : \xf0\x9f\x8d\x93'
Quelques références