TP – afficheurs d’octets UTF8

Prérequis :

Se souvenir du cours sur l’utf8, comme ici.

NSI première : C’était pour mercredi 1er avril

ISN terminale : c’est le TP du jeudi 2 avril

Réaliser une fonction affiche_octets_utf8 qui … affiche les octets (en binaire) d’un caractère (encodé en utf8) envoyé en paramètre d’entrée (ou en argument si vous préférez).

Le découpage fonctionnel est le suivant :

def un_octet(chaine_de_bits):
    # renvoie par exemple pour l'espace :
    # 00100000
    # pour le A (code 65) :
    # 01000001
def deux_octets(c):
    # renvoie par exemple pour é :
    # 11000011 10101001
def trois_octets(c):
    # renvoie par exemple pour €  :
    # 11100010 10000010 10101100

def quatre_octets(c):
    # attention deux cas ici

def affiche_octets_utf8(caractere):
    # utilise une fonction native de python
    # pour avoir les bits de l'écriture binaire
    # et suivant la longueur ce cette chaîne binaire appelle
    # l'une des quatre fonctions ci-dessus
    # en leur envoyant la chaîne binaire pour qu'elles
    # renvoie les octets

print(affiche_octets_utf8(' '))
print(affiche_octets_utf8('A'))
print(affiche_octets_utf8('é'))
print(affiche_octets_utf8('€'))
print(affiche_octets_utf8(chr(2 ** 15)))
print("C'est le glyphe ou caractère pour un code de 2 ** 15")
print("D'après google translate, voudrait dire 'Yào' soit briller en chinois !")
print("L'afficheur quatre octets est un peu virtuel :")
print("Pas de code unicode à quatre octets à ce jour ...")
print("... compatibles avec Python 3.")
print("Mais, avec la fonction quatre_octets, un code de")

for k in range(17, 21):
    print("2 **", k, "doit afficher", quatre_octets(bin(2 ** k)[2:]))
    print("(" + str(k + 1) + " bits)")

Et ce code doit afficher :

  est codé sur 1 octet (ASCII) : 00100000
A est codé sur 1 octet (ASCII) : 01000001
é est codé sur 2 octets : 11000011 10101001
€ est codé sur 3 octets : 11100010 10000010 10101100
耀 est codé sur 3 octets : 11101000 10000000 10000000
C'est le glyphe ou caractère pour un code de 2 ** 15
D'après google translate, voudrait dire 'Yào' soit briller en chinois !
L'afficheur quatre octets est un peu virtuel :
Pas de code unicode à quatre octets à ce jour ...
... compatibles avec Python 3.
Mais, avec la fonction quatre_octets, un code de
2 ** 17 doit afficher 11110000 10100000 10000000 10000000
(18 bits)
2 ** 18 doit afficher 11110001 10000000 10000000 10000000
(19 bits)
2 ** 19 doit afficher 11110010 10000000 10000000 10000000
(20 bits)
2 ** 20 doit afficher 11110100 10000000 10000000 10000000
(21 bits)
>>>

A finir pour les courageux !

 

J’ai donné ce début de code sur discord

def un_octet(chaine_de_bits):
    '''renvoie par exemple pour l'espace : 00100000
    pour le A (code 65) : 01000001'''
    longueur = len(chaine_de_bits)
    nb_zeros = 8 - longueur
    return nb_zeros * '0' + chaine_de_bits #'00' + '100000'

def deux_octets(c):
    '''renvoie par exemple pour é : 11000011 10101001'''
    deuxieme_octet = '10' + c[-6:]
    premier_octet = '110' + '0' * (5 - len(c[:-6])) + c[:-6]
    return premier_octet + ' ' + deuxieme_octet

def affiche_octets_utf8(caractere):
    # utilise une fonction native de python
    # pour avoir les bits de l'écriture binaire
    code = ord(caractere)
    chaine = bin(code)
    chaine = chaine[2:]
    log2 = len(chaine)

    if log2 > 8:
        return un_octet(chaine)
    elif log2 > 12:
        return deux_octets(chaine)

    # et suivant la longueur ce cette chaîne binaire appelle
    # l'une des quatre fonctions ci-dessus
    # en leur envoyant la chaîne binaire pour qu'elles
    # renvoie les octets

print(affiche_octets_utf8(' ')) # 32 -> 00 100000
print(affiche_octets_utf8('A')) # 65 -> 0 1000001
print(affiche_octets_utf8('é'))

Et ces explications dans le shell

>>> 'é'
'é'
>>> chr(65)
'A'
>>> ord('é')
233
>>> bin(ord('é'))
'0b11101001'
>>> bin(233)
'0b11101001'
>>> hex(233)
'0xe9'
>>> bin(233)
'0b11101001'
>>> bin(ord('é'))
'0b11101001'
>>> bin(ord('é'))[0]
'0'
>>> bin(ord('é'))[1]
'b'
>>> bin(ord('é'))[0:2]
'0b'
>>> bin(ord('é'))[2:]
'11101001'
>>> bin(ord('A'))[2:]
'1000001'
>>> bin(ord(' '))[2:]
'100000'
>>> '0' * 2 + bin(ord(' '))[2:]
'00100000'
>>> 2 ** 15
32768
>>> 2 ** 17
131072
>>> 2 ** 16
65536
>>> print(chr(2 ** 15))
耀
>>> chr(108)
'l'
>>> bin(ord('€'))[2:]
'10000010101100'
>>> len(bin(ord('€'))[2:])
14
>>>

TP pygame – saisie et affichages, vers l’utf8

Question flash :

Compléter en suivant ce que disent les commentaires :

# import bibliothèque adaptée

def jeu(pseudo) :
    # calcule un aléatoire entre 12 et 36
    # affiche que le pseudo dans la variable pseudo a fait ce score
    # renvoie le score
>>> jeu("La belle au bois dormant")
La belle au bois dormant a fait 18
18
>>>

Réponse lors du chat discord :

# import bibliothèque adaptée
from random import randint

def jeu(pseudo) :
    # calcule un aléatoire entre 12 et 36
    score = randint(12, 36)
    # affiche que le pseudo dans la variable pseudo a fait ce score
    print(pseudo, "a fait", score)
    # renvoie le score
    return score

Dans le shell :

>>> jeu("Gaëtan")
Gaëtan a fait 23
23
>>>

TP pygame – saisie et affichages, vers l’utf8

Les fichiers de départ sont ici.

« gestion des scores » lors du chat discord :

import pickle

def initialise():
    # liste des scores au cas où
    return [(42, "Mr Marchant !"),(28,"Superman"),(21, "Kirsten Dunst"),(5, "Le Joker")]

def enregistre(liste):
    # Sauvegarde de la liste dans le même dossier dans un fichier
    fichier = open('scores_dump', 'wb')
    # 'wb' comme write en binaire
    pickle.dump(liste, fichier)
    fichier.close() # libérer délivrer le fichier

def charge() :
    fichier = open('scores_dump', 'rb')
    # 'rb' comme read en binaire
    liste = pickle.load(fichier)
    fichier.close() # libérer délivrer le fichier

    return liste

scores = initialise()
for truc in scores:
    print(truc[1], "\t",truc[0])
print()

scores.remove((28,"Superman"))
for truc in scores:
    print(truc[1], "\t",truc[0])

# scores.append((36, "Gaëtan !"))

print()
scores = charge()
for truc in scores:
    print(truc[1], "\t",truc[0])
# enregistre(scores)

Un fichier scores_dump est apparu dans le dossier !

On enlève la fin et le fichier « gestion_scores.py » contient :

import pickle

def initialise():
    # liste des scores au cas où
    return [(42, "Mr Marchant !"),(28,"Superman"),(21, "Kirsten Dunst"),(5, "Le Joker")]

def enregistre(liste):
    # Sauvegarde de la liste dans le même dossier dans un fichier
    fichier = open('scores_dump', 'wb')
    # 'wb' comme write en binaire
    pickle.dump(liste, fichier)
    fichier.close() # libérer délivrer le fichier

def charge() :
    fichier = open('scores_dump', 'rb')
    # 'rb' comme read en binaire
    liste = pickle.load(fichier)
    fichier.close() # libérer délivrer le fichier

    return liste

On explique que les constantes sont en MAJUSCULES comme dans le fichiers parametres.py.

Dans le fichier « tableau_des_scores.py

Les lignes ci-dessous permettent d’importer les fonctions et CONSTANTES de nos fichiers qui deviennent des « bibliothèques perso ».

Ceci permet de partager les fonctionnalités dans un binôme/trinôme !

from parametres import *
from prog_jeu import jeu
from gestion_scores import charge, enregistre, initialise

N.B. : un dossier « py_cache » est alors apparu avec nos modules « pré-interprétées »

Les trois « boulots » demandés :

« Boulot 1 »

###########################

    # BOULOT 1 -> trier les scores

    ##############################

    scores_tries = sorted(scores, reverse = True)
    # for truc in scores_tries:
    #    print(truc[1], "\t",truc[0])

« Boulot 2 »

    ordonnee = ORD_DEPART

    ####################################

    #BOULOT 2

    ###################################

    for truc in scores_tries[:5]: # les 5 premiers
        text2 = font.render(str(truc[0]), 1, BLANC)
        fenetre.blit(text2, (ABS_SCORES, ordonnee))
        text2 = font.render(truc[1], 1, BLANC)
        fenetre.blit(text2, (ABS_NOMS, ordonnee))
        ordonnee += PAS_ORD

« Boulot 3 »

            #######################################

            # BOULOT 3

            ######################################

            elif event.key == K_BACKSPACE:
                pseudo = pseudo[:-1] # enlève la dernière
            elif event.key == K_RETURN:
                # jeu de ouf
                score = jeu(pseudo)
                scores.append((score, pseudo))
            elif len(pseudo) < 18:
                pseudo += event.dict['unicode']

Codage des caractères

ASCII, la norme ancestrale mais inchangée pour les caractères dont le « point de code » est strictement inférieur à 128. La trace de ce qui a été tapé pendant la séance :

>>> ord('u') # le code de 'u' ( ord donne le code )
117                 # les minuscules de 97 à 122
>>> ord('U')        # le code de 'U' est 85
85
>>> ord('A')        # les majuscules de 'A' en 65 à ...
65
>>> ord('Z')
90                  # .... 'Z' en 90
>>> chr(65)         # chr donne le caractère correpondant à un code
'A'
>>> for i in range(32, 128) : chr(i) # avant 32 pas imprimables

' '     # espace en 32
'!'     # là on est en 33
'"'     # je vais les mettre l'un à côté de l'autre, c'est long ...
'#' '$' '%' '&' "'" '(' ')' '*' '+' ',' '-' '.' '/'
# les chiffres : '0' en 48 ... '9' en 57
'0' '1' '2' '3' '4' '5' '6' '7' '8' '9'
':' ';' '&lt;' '=' '&gt;' '?' '@' 'A' 'B' 'C' 'D' 'E' 'F'
'G' 'H' 'I' 'J' 'K' 'L' 'M' 'N' 'O' 'P' 'Q' 'R' 'S'
'T' 'U' 'V' 'W' 'X' 'Y' 'Z' '[' '\\' ']' '^' '_' '`'
# là on est en 97
'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm'
'n' 'o' 'p' 'q' 'r' 's' 't' 'u' 'v' 'w' 'x' 'y' 'z'
'{' '|' '}' '~'
'\x7f'     #pas imprimable
>>> ord('0')  # les chiffres : '0' en 48 ...
48
>>> chr(57)
'9'      # ..... en '9' en 57

Mais ça ne suffit plus !

Les accents européens, les idéogrammes, les caractères cyrilliques, grecs, etc. D’autres… Les smileys …

La norme qui s’est imposée dans les quinze dernières années : l’unicode ou utf-8.

En pratique, tous les systèmes évoluent vers cette norme unifiée pour « tout caractère de n’importe quel système d’écriture (un nom et un identifiant numérique) » : l’Unicode.

La norme UTF-8 est d’un usage de plus en plus courant sur Internet, et dans les systèmes devant échanger de l’information.

C’est une norme rétro-compatible avec l’ASCII initial.

Tous les caractères du « répertoire universel de caractères codés » devant avoir un identifiant unique, un octet ne suffit pas !

Par exemple, le symbole est a un code de 8364 !

Codons 8364 en binaire : 10000010101100.

Il faut non pas 1, non pas 2, non pas 3 mais bien … 14 bits !

L’UTF-8 : de 1 à 4 octets – c’est variable suivant la longueur en bits du code  (à savoir)

cm 2020-01-13 NSI utf8

Pour le symbole , codé 8364 donc 10000010101100 , il faut 14 bits donc 3 octets :

11100010     10000010     10101100    soit      E2   82   AC

Notez que l’UTF-8 demande plus de place que l’ASCII ou d’autres normes intercalées ! C’est le prix de l’universalité.

Les caractères ASCII restent identiques. On parle de rétrocompatibilité de l’utf-8 avec l’ASCII, je le répète (à savoir).

Exercices pour jeudi prochain :

Question 1 :

  • Coder en UTF8 (binaire) le é codé 233.

Question 2 :

  • Combien de caractères différents peut on coder en UTF-8 ?

Question 3 :

On a la séquence de huit octets suivante :

C3 A9 6C C3 A8 76 65 73

où chaque octet est représenté par deux chiffres hexadécimaux.

    • C’est en UTF-8, décoder la séquence.

Information, représentation des données (3)

On a vue ensemble l’écriture binaire de nombres décimaux.

Il reste à voir comment ils peuvent être codés en mémoire. Pour cela, les normes en vigueur définissent les flottants, en simple précision sur 32 bits (float), et en double précision sur 64 bits (double).

Je vous propose de commencer par ce petit test pour rassembler vos connaissances et découvrir et vous frotter aux difficultés du jour :

On ne triche pas et on cherche avant de continuer !

On suppose que vous avez bien cherché… On va tout détailler !

cm 2020-03-19 ISN virgule flottante 01

cm 2020-03-19 ISN virgule flottante 02

cm 2020-03-19 ISN virgule flottante 03

On explique pourquoi :

>>> 0.1 + 0.1 + 0.1
0.30000000000000004
>>>

cm 2020-03-19 ISN virgule flottante 04

Remarque : attention aux codes avec les flottants !

« 0.2 + 0.1 n’est pas égal à 0.3. Il faut éviter de tester l’égalité de deux flottants. »

Illustrons-le avec un petit code python très maladroit :

nombre = 0.1

while nombre != 1 :
    nombre += 0.1
    print(nombre)

Il faut en effet éviter de tester l’égalité de deux flottants :

>>> 
======== RESTART: cm 2020-02-03 NSI exemple1.py ========
0.2
0.30000000000000004
0.4
0.5
0.6
0.7
0.7999999999999999
0.8999999999999999
0.9999999999999999
1.0999999999999999
1.2
1.3
...

Il nous a fallu une interruption (Ctrl-C) pour ce programme qui tournait en boucle infinie !

Conclusion pour l’oral du bac ISN ?

Encore un exercice ?

cm 2020-03-19 ISN virgule flottante 05cm 2020-03-19 ISN virgule flottante 06

A mettre en simple précision sur 32 bits.

On peut vérifier avec ce convertisseur :

  • 6,625 donne 01000000 11010100 00000000 00000000
  • 5,4375 donne 01000000 10101110 00000000 00000000

 

Enseignement à distance

Bonjour chères et chers élèves, et leurs responsables légaux,

On va essayer de relever le défi de l’enseignement à distance et de la « continuité pédagogique ».


Je mettrai tout le contenu (et les discussions se feront) sur le site que vous êtes en train de consulter :

J’ai fait des tests vidéos (devenus inutiles) et aussi audio.

Le format au 17 mars :

  • des enregistrements audios avec supports pdf,
  • entrecoupés d’exercices à faire,
  • des corrigés ensuite (audios et supports pdf)
  • avec les documents à côté.

Intéragir ?

  • via les commentaires des articles de ce site,
  • via les salons de discussion ou « chat » mis en place par les terminales pour les terminales. J’attends un(e) élève de première NSI pour faire de même.

Mise à jour du 16 mars : ce ne sera pas au TBI, même les enseignants ne devraient pas aller au lycée. Je réfléchis à la meilleure formule. Mais je compte bien essayer de faire quelque chose de plus formateur qu’un simple partage de documents.

Mise à jour 17 mars : on part sur du document publié avec des commentaires audio, comme celui ci-dessous. Pour toute question passer par les commentaires.

Les TS1 et certainement les élèves de spé ISN en terminale, vos délégués ont mis en place un serveur discord pour organiser des salons de discussion. Tournez-vous vers eux en cas de problème technique. Ces salons se dérouleront à la demande, mais surtout pendant les heures normales de cours

  • de maths le mardi à 14h00, mercredi 10h30 et jeudi 8h30.
  • d’ISN le jeudi 10h00. @TS2 : contactez des TS1 pour rejoindre le salon !

Je n’oublie pas mes NSI de première adorés 😳 , mais on part sur une formule pdf + commentaires audio dès demain. Je vous enverrai certainement dans les semaines à venir vers un cours en ligne existant, mais toujours avec mon aide distante.

Certaines vidéos ou cours en ligne existants seront indiqués.

TS1 Maths :

  • Je ferai un corrigé du DM mercredi, et un corrigé des exercices sur la loi normale.
  • Je traiterai les chapitres A8 (ln) et A11 (primitives), A12 (calcul intégral) dans cet ordre.

NSI première :

  • Je vais commencer des nouveaux chapitres, des nouvelles mercredi.

ISN terminale :

  • La priorité est de lancer les projets. Une page de discussion dédiée dès jeudi.

Courage et pas de panique, on va essayer de bien faire ensemble ! Avec … ambition, et humilité 😉

Christophe Marchant

Information, représentation des données (2)

Suite de notre voyage dans le codage de l’information…

Question flash :

« comment est codé -144 sur 32 bits ? »

Correction :

Algorithme de conversion à faire pour aujourd’hui :

  • de décimal vers binaire,

et réciproquement ?

Codage des décimaux : les flottants

  • nombres décimaux en binaire,
  • algorithme pour avoir le développement décimal binaire,
  • à suivre le 19/3, les normes : float et double.

Le tableau du jour (une seule heure) :

Information, représentation des données

On y a parlé d’écriture

  • binaire des nombres entiers non signés,
  • hexadécimale de mêmes nombres entiers non signés,
  • fait un rappel sur les pixels et la notation html des couleurs :cm 2020-02-06 ISN code couleur d7d03d
  • abordé ensuite des algorithmes de conversion du décimal au binaire :
    • comme on le fait « à la main »,
    • par divisions successives par deux,
  • expliqué l’encodage des entiers signés.

Tout est dans les tableaux ci-dessous :

Coder le deuxième algorithme de conversion vers le binaire donné pendant ce cours, par divisions successives par deux, celui du cinquième tableau au début de la troisième page, pour la rentrée.

Bonnes vacances !

TP improvisé : pile ou file ?

Mini-projets et site web les présentant :

Une collecte a été mise en place pour les rendus sur l’espace numérique de travail (MBN) du lycée.

Exposé du jour :

Septième et dernier exposé de notre cycle par Alex & Tom :

Parcours des graphes et application aux labyrinthes, pile et file

TP improvisé – application de la pile

Il y a huit présents pour sept absents (JU…) ! Plutôt que de péter une pile, on en a utilisé une…

On s’appuie sur le TP des premières NSI de ce mercredi pour, en deux étapes :

  • implémenter les déplacements clavier, dans une boucle while continuer : « perpétuelle » où continuer est initialisée à True et on attend des événements (clavier, souris) pour des actions ou quitter la boucle en passant continuer à False.
  • tout changer, CHANGER DE PARADIGME : passer à un algorithme itératif en utilisant notre nouvelle structure de données, la pile :

cm 2020-01-30 ISN changement de paradigme pour parcous

À droite l’algorithme suivi, par exemple par Corentin « B. de B. », qui a obtenu ceci :

cm 2020-01-31 tp4_parcours profondeur B de B

C’est un parcours en profondeur, « à gauche d’abord » (du point de vue du personnage) ! On a utilisé une pile,

  • initialisé la pile avec pile = []
  • empilé avec pile.append((x, y))
  • dépilé avec x, y = pile.pop()

En changeant cette dernière commande en lui ajoutant un paramètre, on obtient une file,

  • initialisé la file avec file = []
  • emfilé avec file.append((x, y))
  • dépilé avec x, y = file.pop(0)

Et au niveau du parcours, ça change tout : on a un parcours en largeur :

cm 2020-01-31 tp4_parcours largeur B de B