You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests.
 
 
 
 
 
 

310 lines
6.8 KiB

  1. Données binaires
  2. ================
  3. Introduction : chiffres et nombres
  4. -----------------------------------
  5. Si je vous parle de ce que représente le texte: ``342`` vous pouvez le
  6. voir de deux façons:
  7. 1. C'est une **suite de chiffres**: ``3``, puis ``4``, puis ``2``.
  8. 1. C'est un **nombre** (quelque part entre 300 et 350)
  9. On se sert des *chiffres* de 0 à 9 pour *représenter* des *nombres*
  10. La base 10
  11. ----------
  12. Plus exactement, pour passer de la suite de chiffres ``342`` au nombre,
  13. on part de la fin, puis on ajoute chaque chiffre, multiplié par la puissance
  14. de 10 adéquate::
  15. 2 * 1
  16. + 4 * 10
  17. + 2 * 10 * 10
  18. soit::
  19. 2
  20. + 40
  21. + 300
  22. ce qui fait bien 342.
  23. La base 16
  24. ----------
  25. En informatique, on se sert souvent de la base 16. C'est le même principe: on se
  26. sert des "chiffres" de 0 à F (A vaut 10, B vaut 11, jusqu'à F qui vaut 15)
  27. Ainsi, la suite ``DA2`` peut être interprétée comme suit ::
  28. 2 * 1
  29. + 10 * 16
  30. + 13 * 16 * 16
  31. soit ::
  32. 2
  33. + 160
  34. + 3328
  35. soit 3746
  36. On appelle aussi la base 16 la base *hexadécimale*, ou *hexa* en abrrégé.
  37. La base 2
  38. ----------
  39. La base 2 c'est pareil, mais avec deux "chiffres" - 0 et 1.
  40. Ainsi, la suite `110` peut être interprétée comme suit ::
  41. 0 * 1
  42. + 1 * 2
  43. + 1 * 2 * 2
  44. soit ::
  45. 0
  46. + 2
  47. + 4
  48. soit 6.
  49. Bits et octets
  50. --------------
  51. * Un bit (*bit* en anglais) c'est la valeur 1 ou 0
  52. * Un octet (*byte* en anglais) c'est une suite de 8 bits
  53. À retenir
  54. ---------
  55. **Ces paquets de 8 ne veulent rien dire en eux-mêmes**.
  56. Ils n'ont de sens que dans le cadre d'une *convention*.
  57. Par exemple, l'octet '10100100' peut être un nombre écrit en
  58. binaire (164 en l'occurrence), mais peut avoir une toute
  59. autre signification
  60. Le nombre de valeurs possible augmente *très* rapidement avec le nombre d'octets:
  61. * 1 octet, c'est 255 valeurs possibles (``2 ** 8``)
  62. * 2 octets, c'est 65.536 valeurs possibles (``2 ** 16``)
  63. * 4 octets, c'est 4.294.967.296 valeurs possibles (``2 ** 32``)
  64. Bases en Python
  65. ---------------
  66. On se sert des préfixes `0b` et `0x` pour noter
  67. les nombres en base binaire ou hexadécimale respectivement::
  68. print(0b1110)
  69. # affiche: 6
  70. print(0xDA2)
  71. # affiche: 3490
  72. Poids des bits
  73. --------------
  74. Regardez l'example suivant::
  75. x = 0b0010010 # 18
  76. y = 0b0010011 # 19
  77. z = 0b1010010 # 82
  78. Notez que le premier bit est plus "fort" que le dernier on dit qu'on est en "little endian".
  79. Manipuler des octets en Python
  80. ------------------------------
  81. On peut construrie des listes d'octets en utilsant ``bytearray`` et
  82. une liste de nombres::
  83. data = bytearray(
  84. [0b1100001,
  85. 0b1100010,
  86. 0b1100011
  87. ]
  88. )
  89. # equivalent:
  90. data = bytearray([97,98,99])
  91. # equivalent aussi:
  92. data = bytearray([0x61, 0x62, 0x63]
  93. Texte
  94. -----
  95. On peut aussi interpréter des octets comme du texte - c'est la table ASCII
  96. .. image:: ../img/ascii-table.png
  97. ASCII - remarques
  98. -----------------
  99. * C'est *vieux* - 1960
  100. * Le A est pour American
  101. * Ça sert à *envoyer* du texte sur des terminaux d'où les "caractères" non-imprimables dans la liste
  102. * Mais c'est une convention *très* utilisée
  103. * Techniquement, on n'a besoin que de 7 bits, mais on préfère envoyer des octets
  104. Utiliser ASCII en Python
  105. ------------------------
  106. Avec ``chr`` et ``ord``::
  107. x = chr(98)
  108. print(x)
  109. # affiche: b
  110. x = ord('a')
  111. print(x)
  112. # affiche: 97
  113. Affichage des bytearrays en Python
  114. ----------------------------------
  115. Python utilise ASCII pour afficher les bytearrays si les caractères sont "imprimables"::
  116. data = bytearray([97,98,99])
  117. print(data)
  118. # affiche: bytearray(b"abc")
  119. Et ``\x`` et le code hexa sinon::
  120. data = bytearray([7, 69, 76, 70])
  121. print(data)
  122. # affiche: bytearray(b"\x07ELF")
  123. Notez bien que ce qu'affiche Python n'est qu'une *interpétation* d'une séquence d'octets.
  124. Types
  125. -----
  126. La variable `b"abc"` est une "chaîne d'octets", de même que `"abc"` est une "chaîne de caractères".
  127. Python apelle ces types `bytes` et `str`::
  128. print(type("abc"))
  129. # affiche: str
  130. print(type(b"abc"))
  131. # affiche: bytes
  132. bytes et bytearray
  133. ------------------
  134. De la même manière qu'on ne peut pas modifier un caractère à l'intérieur une string, on ne peut
  135. pas modifier un bit - ou un octet dans une variable de type `bytes`::
  136. a = "foo"
  137. # a[0] = "f" => TypeError: 'str' object does not support item assignment
  138. b = b"foo"
  139. # b[0] = 1 => TypeError: 'bytes' object does not support item assignment
  140. Par contre on peut modifier un bytearray::
  141. b = bytearray(b"foo")
  142. b[0] = 103
  143. print(b)
  144. # affiche: bytearray(b"goo")
  145. Conversion bytes - texte
  146. ------------------------
  147. Avec ``encode()`` et ``decode()``::
  148. text = "chaise"
  149. encodé = text.encode("ascii")
  150. print(encodé)
  151. # affiche: b"chaise"
  152. bytes = b"table"
  153. décodé = bytes.decode("ascii")
  154. print(décodé)
  155. # affiche: b"table"
  156. Notez que dans le deuxième exemple, on est bien en train de "décoder"
  157. un paquet de 0 et de 1. Il peut s'écrire ainsi:
  158. bytes = b"\x74\x61\x62\x6c\x65"
  159. décodé = bytes.decode("ascii")
  160. print(décodé)
  161. # affiche: table
  162. Plus loin que l'ASCII
  163. ---------------------
  164. Vous avez sûrement remarquer qu'il n'y a pas de caractères accentués dans
  165. ASCII. Du coup, il existe d'autres *conventions* qu'on appelle "encodage".
  166. On peut spécifier l'encodage quand on appelle la méthode ``decode()``::
  167. # latin-1: utilisé sur certains vieux sites
  168. data = bytearray([233])
  169. lettre = data.decode('latin-1')
  170. print(lettre)
  171. # affiche: 'é'
  172. # cp850: dans l'invite de commande Windows
  173. data = bytearray([233])
  174. lettre = data.decode('cp850')
  175. print(lettre)
  176. # affiche: 'Ú'
  177. Notez que la même suite d'octets a donné des résultats différents en fonction
  178. de l'encodage!
  179. Unicode
  180. --------
  181. L'Unicode c'est deux choses:
  182. 1. Une **table** qui associe un un "codepoint" à chaque caractère
  183. 2. Un encodage particulier, l'UTF-8, qui permet de convertir une suite
  184. d'octets en suite de codepoint et donc de caractères
  185. UTF-8 en pratique
  186. ------------------
  187. D'abord, UTF-8 est compatible avec ASCII::
  188. encodé = "abc".encode("utf-8")
  189. print(encodé)
  190. # Affiche: b'abc'
  191. Ensuite, certains caractères (comme ``é``) sont représentés par 2 octets::
  192. encodé = "café".encode("utf-8")
  193. print(encodé)
  194. # Affiche: b'caf\xc3\xa9"
  195. Enfin, certains caractères (comme les emojis) sont représentés par 3 voire plus octets.
  196. .. warning::
  197. Toutes les séquences d'octets ne sont pas forcément valides quand on veut
  198. les décoder en UTF-8
  199. Conséquences
  200. -------------
  201. * On peut représenter *tout* type de texte avec UTF-8 (latin, chinois, coréen, langues disparues, ....)
  202. * On ne peut pas accéder à la n-ème lettre directement dans une chaîne
  203. encodée en UTF-8, il faut parcourir lettre par lettre (ce qui en pratique est rarement
  204. un problème).