Aller au contenu

Exercices - Représentation des données : types et valeurs de base


Entiers positifs et bases de numération

Exercice 1 - Conversions binaire vers décimal

Convertir les nombres binaires suivants en décimal.

a. \((1010)_2\)

b. \((11001)_2\)

c. \((10000000)_2\)

d. \((11111111)_2\)

e. \((101010)_2\)

Solution

a. \((1010)_2\) = 1×8 + 0×4 + 1×2 + 0×1 = 10

b. \((11001)_2\) = 1×16 + 1×8 + 0×4 + 0×2 + 1×1 = 25

c. \((10000000)_2\) = 1×128 = 128

d. \((11111111)_2\) = 128 + 64 + 32 + 16 + 8 + 4 + 2 + 1 = 255

e. \((101010)_2\) = 32 + 8 + 2 = 42


Exercice 2 - Conversions décimal vers binaire

Convertir les nombres décimaux suivants en binaire (méthode des divisions successives).

a. 13

b. 100

c. 200

d. 255

e. 1 024

Solution

a. 13 = \((1101)_2\)

Division Quotient Reste
13 ÷ 2 6 1
6 ÷ 2 3 0
3 ÷ 2 1 1
1 ÷ 2 0 1

Lecture de bas en haut : 1101

b. 100 = \((1100100)_2\)

100 = 64 + 32 + 4 = 2⁶ + 2⁵ + 2² → 1100100

c. 200 = \((11001000)_2\)

200 = 128 + 64 + 8 = 2⁷ + 2⁶ + 2³ → 11001000

d. 255 = \((11111111)_2\)

255 = 2⁸ - 1, donc 8 bits tous à 1 → 11111111

e. 1 024 = \((10000000000)_2\)

1 024 = 2¹⁰ → un 1 suivi de 10 zéros.


Exercice 3 - Hexadécimal

a. Convertir en décimal : \((3F)_{16}\), \((FF)_{16}\), \((1A)_{16}\), \((100)_{16}\)

b. Convertir en hexadécimal : 31, 255, 512, 1000

c. Convertir en binaire : \((B4)_{16}\), \((7E)_{16}\)

d. Convertir en hexadécimal : \((11010110)_2\), \((10011111)_2\)

Solution

a.

  • \((3F)_{16}\) = 3×16 + 15 = 63
  • \((FF)_{16}\) = 15×16 + 15 = 255
  • \((1A)_{16}\) = 1×16 + 10 = 26
  • \((100)_{16}\) = 1×256 = 256

b.

  • 31 : 31 ÷ 16 = 1 reste 15 (F) → \((1F)_{16}\)
  • 255 : 255 ÷ 16 = 15 (F) reste 15 (F) → \((FF)_{16}\)
  • 512 : 512 ÷ 16 = 32, 32 ÷ 16 = 2 reste 0 → \((200)_{16}\)
  • 1000 : 1000 ÷ 16 = 62 reste 8, 62 ÷ 16 = 3 reste 14 (E) → \((3E8)_{16}\)

c.

  • \((B4)_{16}\) : B = 1011, 4 = 0100\((10110100)_2\)
  • \((7E)_{16}\) : 7 = 0111, E = 1110\((01111110)_2\)

d.

  • \((11010110)_2\) : 1101 = D, 0110 = 6 → \((D6)_{16}\)
  • \((10011111)_2\) : 1001 = 9, 1111 = F → \((9F)_{16}\)

Exercice 4 - Nombre de bits

a. Combien de bits faut-il pour représenter le nombre 150 ?

b. Combien de valeurs différentes peut-on coder sur 12 bits ?

c. On dispose de 20 bits. Quel est le plus grand entier positif que l'on peut représenter ?

d. Un fichier image contient 1 000 000 de pixels. Chaque pixel est codé sur 24 bits (8 bits par couleur : rouge, vert, bleu). Quelle est la taille du fichier en octets ? En mégaoctets (1 Mo = 10⁶ octets) ?

Solution

a. 2⁷ = 128 < 150 <= 255 = 2⁸ - 1, donc il faut 8 bits.

b. 2¹² = 4 096 valeurs différentes (de 0 à 4 095).

c. 2²⁰ - 1 = 1 048 575.

d. 1 000 000 × 24 bits = 24 000 000 bits = 24 000 000 / 8 = 3 000 000 octets = 3 Mo.


Entiers relatifs et complément à 2

Exercice 5 - Codage en complément à 2

Coder les nombres suivants en complément à 2 sur 8 bits.

a. +18

b. -18

c. -1

d. -100

e. -128

Solution

a. +18 : on code 18 en binaire sur 8 bits → 00010010

b. -18 :

  1. 18 en binaire : 00010010
  2. Inversion : 11101101
  3. Ajout de 1 : 11101110

Résultat : 11101110

c. -1 :

  1. 1 en binaire : 00000001
  2. Inversion : 11111110
  3. Ajout de 1 : 11111111

Résultat : 11111111

d. -100 :

  1. 100 en binaire : 01100100
  2. Inversion : 10011011
  3. Ajout de 1 : 10011100

Résultat : 10011100

e. -128 :

  1. 128 en binaire : 10000000
  2. Inversion : 01111111
  3. Ajout de 1 : 10000000

Résultat : 10000000 (c'est le plus petit entier sur 8 bits)


Exercice 6 - Décodage du complément à 2

Donner la valeur décimale des nombres suivants, codés en complément à 2 sur 8 bits.

a. 01001100

b. 10000001

c. 11110000

d. 10101010

Solution

a. 01001100 : le bit de poids fort est 0, donc positif. 64 + 8 + 4 = 76

b. 10000001 : bit de poids fort = 1, donc négatif.

  • Inversion : 01111110
  • Ajout de 1 : 01111111 = 127
  • Résultat : -127

c. 11110000 : négatif.

  • Inversion : 00001111
  • Ajout de 1 : 00010000 = 16
  • Résultat : -16

d. 10101010 : négatif.

  • Inversion : 01010101
  • Ajout de 1 : 01010110 = 64 + 16 + 4 + 2 = 86
  • Résultat : -86

Exercice 7 - Dépassement de capacité

On travaille sur 8 bits en complément à 2.

a. Quel est l'intervalle des valeurs représentables ?

b. Calculer 120 + 30 en binaire sur 8 bits. Que se passe-t-il ?

c. Calculer -100 + (-50) en binaire sur 8 bits. Que se passe-t-il ?

Solution

a. De -128 à +127.

b. 120 + 30 = 150, mais 150 > 127 : il y a dépassement de capacité.

  01111000   (120)
+ 00011110   (30)
----------
  10010110   (-106 en complément à 2)

Le résultat est interprété comme -106 au lieu de 150. Le bit de signe est passé à 1 par erreur.

c. -100 + (-50) = -150, mais -150 < -128 : dépassement également.

-100 = 10011100, -50 = 11001110

  10011100   (-100)
+ 11001110   (-50)
----------
1 01101010   (+106 en complément à 2, retenue ignorée)

Le résultat est interprété comme +106 au lieu de -150.


Nombres flottants

Exercice 8 - Conversion en binaire de nombres à virgule

Convertir les nombres suivants en binaire.

a. 0,5

b. 0,625

c. 5,75

d. 0,1 (donner les 8 premiers bits après la virgule)

Solution

a. 0,5 = 1/2 = 2⁻¹ → \((0,1)_2\)

b. 0,625 = 0,5 + 0,125 = 2⁻¹ + 2⁻³ → \((0,101)_2\)

c. 5,75 = 5 + 0,75

  • Partie entière : 5 = \((101)_2\)
  • Partie décimale : 0,75 = 0,5 + 0,25 = \((0,11)_2\)
  • Résultat : \((101,11)_2\)

d. 0,1 par multiplications successives par 2 :

Étape Calcul Bit
1 0,1 × 2 = 0,2 0
2 0,2 × 2 = 0,4 0
3 0,4 × 2 = 0,8 0
4 0,8 × 2 = 1,6 1
5 0,6 × 2 = 1,2 1
6 0,2 × 2 = 0,4 0
7 0,4 × 2 = 0,8 0
8 0,8 × 2 = 1,6 1

0,1 ≈ \((0,00011001...)_2\) (la séquence 0011 se répète)


Exercice 9 - Erreurs d'arrondi

Sans exécuter le code, prédire ce qu'affiche chaque instruction Python. Vérifier ensuite dans la console.

a. 0.1 + 0.2 == 0.3

b. 0.5 + 0.25 == 0.75

c. 0.1 + 0.1 + 0.1 == 0.3

d. 0.1 * 10 == 1.0

e. abs(0.1 + 0.2 - 0.3) < 1e-10

Solution

a. False : 0,1 et 0,2 ne sont pas exacts en binaire, leur somme n'est pas exactement 0,3.

b. True : 0,5 = 2⁻¹ et 0,25 = 2⁻² sont exacts en binaire, tout comme 0,75.

c. False : trois additions de 0,1 accumulent les erreurs d'arrondi.

d. False : 0.1 * 10 donne 1.0000000000000002 (vérifier dans la console).

e. True : la différence 0.1 + 0.2 - 0.3 est d'environ 5,5 × 10⁻¹⁷, bien inférieure à 10⁻¹⁰. C'est la bonne façon de comparer des flottants.


Booléens et expressions booléennes

Exercice 10 - Tables de vérité

Dresser la table de vérité de chaque expression.

a. a or (not b)

b. (a and b) or (a and (not b))

c. not (a or b)

Solution

a. a or (not b)

a b not b a or (not b)
0 0 1 1
0 1 0 0
1 0 1 1
1 1 0 1

b. (a and b) or (a and (not b))

a b not b a and b a and (not b) Résultat
0 0 1 0 0 0
0 1 0 0 0 0
1 0 1 0 1 1
1 1 0 1 0 1

On remarque que le résultat est identique à a : l'expression se simplifie en a.

c. not (a or b) (loi de De Morgan : équivalent à (not a) and (not b))

a b a or b not (a or b)
0 0 0 1
0 1 1 0
1 0 1 0
1 1 1 0

Exercice 11 - Évaluation paresseuse

Pour chaque expression, indiquer si Python provoque une erreur ou renvoie un résultat. Justifier.

a. True or (1 / 0 > 0)

b. False and (1 / 0 > 0)

c. True and (1 / 0 > 0)

d. False or (1 / 0 > 0)

e. (5 > 3) or (10 / 0 == 1)

Solution

a. Renvoie True sans erreur. Le or court-circuite car le premier opérande est True.

b. Renvoie False sans erreur. Le and court-circuite car le premier opérande est False.

c. Erreur ZeroDivisionError. Le and évalue le second opérande car le premier est True.

d. Erreur ZeroDivisionError. Le or évalue le second opérande car le premier est False.

e. Renvoie True sans erreur. 5 > 3 est True, donc le or court-circuite.


Exercice 12 - Addition binaire

Effectuer les additions binaires suivantes. Vérifier en convertissant en décimal.

a. \((1010)_2\) + \((0101)_2\)

b. \((1100)_2\) + \((1010)_2\)

c. \((1111)_2\) + \((0001)_2\)

Solution

a.

  1 0 1 0   (10)
+ 0 1 0 1   (5)
---------
  1 1 1 1   (15)
Vérification : 10 + 5 = 15 ✓

b.

retenues :  1 0 0 0
            1 1 0 0   (12)
          + 1 0 1 0   (10)
          ---------
        1 0 1 1 0     (22)
Vérification : 12 + 10 = 22 ✓

c.

retenues :  1 1 1 1
            1 1 1 1   (15)
          + 0 0 0 1   (1)
          ---------
        1 0 0 0 0     (16)
Vérification : 15 + 1 = 16 ✓


Encodage des textes

Exercice 13 - Code ASCII

a. En utilisant la table ASCII, donner le code de chaque caractère du mot "Info".

b. Décoder la suite de codes ASCII suivante : 66, 111, 110, 106, 111, 117, 114.

c. Quel est le code ASCII de 'a' ? De 'z' ? En déduire combien de lettres minuscules comporte l'alphabet.

d. Écrire une fonction Python est_majuscule(c) qui renvoie True si le caractère c est une lettre majuscule, False sinon.

Solution

a.

  • 'I' → 73
  • 'n' → 110
  • 'f' → 102
  • 'o' → 111

b. 66 = 'B', 111 = 'o', 110 = 'n', 106 = 'j', 111 = 'o', 117 = 'u', 114 = 'r'"Bonjour"

c. ord('a') = 97, ord('z') = 122. Il y a 122 - 97 + 1 = 26 lettres minuscules.

d.

def est_majuscule(c):
    return 65 <= ord(c) <= 90

Ou plus simplement :

def est_majuscule(c):
    return 'A' <= c <= 'Z'


Exercice 14 - Encodage et Python

a. Que renvoie ord('é') en Python ? Pourquoi ce résultat est-il supérieur à 127 ?

b. Écrire un programme Python qui affiche tous les caractères dont le code Unicode est compris entre 945 et 969. De quel alphabet s'agit-il ?

c. Le mot "Café" est enregistré en UTF-8. Combien d'octets occupe-t-il en mémoire ? (Indication : les caractères ASCII occupent 1 octet, les caractères accentués 2 octets en UTF-8.)

Solution

a. ord('é') renvoie 233. Ce résultat est supérieur à 127 car le caractère 'é' n'existe pas dans la table ASCII (limitée à 128 caractères). Son code est défini dans les extensions (Latin-1, Unicode).

b.

for code in range(945, 970):
    print(chr(code), end=" ")
Résultat : α β γ δ ε ζ η θ ι κ λ μ ν ξ ο π ρ ς σ τ υ φ χ ψ ω

C'est l'alphabet grec minuscule.

c. "Café" :

  • C : 1 octet (ASCII)
  • a : 1 octet (ASCII)
  • f : 1 octet (ASCII)
  • é : 2 octets (accentué, code 233 > 127)

Total : 1 + 1 + 1 + 2 = 5 octets


Exercice 15 - Programme : chiffrement de César

Le chiffrement de César consiste à décaler chaque lettre d'un texte d'un nombre fixe de positions dans l'alphabet. Par exemple, avec un décalage de 3 : A devient D, B devient E, ..., Z devient C.

a. Écrire une fonction cesar(texte, decalage) qui chiffre un texte en majuscules par la méthode de César.

b. Tester avec cesar("BONJOUR", 3) (résultat attendu : "ERQMRXU").

c. Comment déchiffrer un message chiffré avec un décalage de 3 ?

Solution

a.

def cesar(texte, decalage):
    resultat = ""
    for caractere in texte:
        if 'A' <= caractere <= 'Z':
            code = ord(caractere) - 65
            nouveau_code = (code + decalage) % 26
            resultat += chr(nouveau_code + 65)
        else:
            resultat += caractere
    return resultat

b.

>>> cesar("BONJOUR", 3)
'ERQMRXU'

c. Pour déchiffrer, on applique le décalage inverse : cesar("ERQMRXU", -3) renvoie "BONJOUR". Autrement dit, déchiffrer un décalage de 3 revient à chiffrer avec un décalage de -3 (ou 23, puisque -3 mod 26 = 23).



Activités


🧪 Activité 1 - Le mystère du nombre 42 (conversions entre bases)

Objectif

S'exercer aux conversions entre les bases 2, 10 et 16 en décodant des messages cachés.

Partie A - Décoder un message secret

Chaque nombre ci-dessous est le code ASCII d'un caractère. Mais attention, ils sont écrits dans des bases différentes !

Valeur Base Caractère ?
1001000 binaire
65 décimal
4C hexadécimal
1001100 binaire
4F hexadécimal

a. Convertir chaque valeur en décimal, puis retrouver le caractère ASCII correspondant pour former un mot.

b. Coder le mot "NSI" de la même manière : un caractère en binaire, un en décimal, un en hexadécimal.

Partie B - Le défi des puissances de 2

c. Compléter le tableau suivant sans calculatrice :

Puissance 2⁰ 2⁴ 2⁵ 2⁶ 2⁷ 2⁸ 2⁹ 2¹⁰
Valeur

d. Pourquoi 1 Ko (kilo-octet en informatique) vaut-il parfois 1 024 octets et non 1 000 ?

Correction

a.

  • 1001000 en binaire = 64 + 8 = 72 → 'H'
  • 65 en décimal → 'A'
  • 4C en hexadécimal = 4×16 + 12 = 76 → 'L'
  • 1001100 en binaire = 64 + 8 + 4 = 76 → 'L'
  • 4F en hexadécimal = 4×16 + 15 = 79 → 'O'

Le mot est "HALLO".

b. "NSI" :

  • N = 78 → en binaire : 1001110
  • S = 83 → en décimal : 83
  • I = 73 → en hexadécimal : 49

c.

Puissance 2⁰ 2⁴ 2⁵ 2⁶ 2⁷ 2⁸ 2⁹ 2¹⁰
Valeur 1 2 4 8 16 32 64 128 256 512 1024

d. Parce que 2¹⁰ = 1 024, la puissance de 2 la plus proche de 1 000. En informatique, les capacités mémoire sont des puissances de 2, d'où cette convention historique. La norme IEC distingue le kilooctet (kB = 1 000 octets) du kibioctet (KiB = 1 024 octets).


🧪 Activité 2 - Le jeu du complément à 2 (entiers relatifs)

Objectif

Comprendre et manipuler le complément à 2 en se mettant dans la peau d'un processeur 8 bits.

Règles du jeu (travail en binôme)

Chaque joueur dispose d'une « mémoire » de 8 cases (8 bits). Un joueur choisit un nombre relatif, l'autre doit le coder en complément à 2 (et vice versa).

Partie A - Codage

a. Coder les nombres suivants en complément à 2 sur 8 bits : +42, -42, +127, -128, 0, -1.

b. Votre partenaire vous donne les nombres suivants en complément à 2. Trouvez leur valeur décimale :

01010101, 10000000, 11111111, 10110100, 00000001

Partie B - L'addition vérifiée par le processeur

c. Effectuer les additions suivantes en binaire sur 8 bits. Pour chaque calcul, vérifier le résultat en décimal.

  • (+25) + (+37)
  • (+50) + (-20)
  • (-60) + (-30)

d. Effectuer l'addition (+100) + (+50) sur 8 bits. Que constate-t-on ? Comment s'appelle ce phénomène ?

Partie C - Réflexion

e. Pourquoi le plus petit nombre sur 8 bits est -128 et non -127 ?

f. Un camarade affirme : « Le nombre -0 existe en complément à 2. » A-t-il raison ? Justifiez.

Correction

a.

  • +42 = 00101010
  • -42 : 42 = 00101010 → inversion 11010101 → +1 = 11010110
  • +127 = 01111111
  • -128 = 10000000
  • 0 = 00000000
  • -1 : 1 = 00000001 → inversion 11111110 → +1 = 11111111

b.

  • 01010101 : positif → 64 + 16 + 4 + 1 = 85
  • 10000000 : négatif → inversion 01111111 → +1 = 10000000 = 128 → -128
  • 11111111 : négatif → inversion 00000000 → +1 = 00000001 = 1 → -1
  • 10110100 : négatif → inversion 01001011 → +1 = 01001100 = 76 → -76
  • 00000001 : positif → 1

c.

  • (+25) + (+37) : 00011001 + 00100101 = 00111110 = 62 ✓
  • (+50) + (-20) : 00110010 + 11101100 = (1)00011110 = 30 (retenue ignorée) ✓
  • (-60) + (-30) : 11000100 + 11100010 = (1)10100110 = -90 (retenue ignorée) ✓

d. (+100) + (+50) = 150, mais la valeur maximale sur 8 bits est 127. 01100100 + 00110010 = 10010110 = -106 en complément à 2. C'est un dépassement de capacité (overflow).

e. Sur 8 bits, les positifs vont de 0 (00000000) à 127 (01111111), soit 128 valeurs. Les négatifs vont de -1 (11111111) à -128 (10000000), soit aussi 128 valeurs. Le 0 « compte » du coté des positifs, d'où l'asymétrie : [-128, +127].

f. Non, il a tort. En complément à 2, il n'y a qu'une seule représentation du 0 : 00000000. Si on applique le procédé du complément à 2 sur 0 : 00000000 → inversion 11111111 → +1 = (1)00000000, la retenue sort des 8 bits et on retrouve 0. C'est un avantage du complément à 2 par rapport à d'autres codages.


🧪 Activité 3 - Les pièges des flottants (investigation Python)

Objectif

Découvrir expérimentalement les limites de la représentation en virgule flottante et comprendre pourquoi il ne faut jamais faire confiance aux décimales d'un flottant.

Partie A - Observer les erreurs

Dans la console Python, tester chaque instruction et noter le résultat.

a. 0.1 + 0.2

b. 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1

c. sum([0.1] * 10)

d. 1.0 - 0.7

e. 0.5 + 0.25

Classer les résultats en deux catégories : « exact » et « inexact ». Quel point commun ont les résultats exacts ?

Partie B - Conséquences pratiques

f. Écrire un programme qui ajoute 0,01 à une variable initialisée à 0, mille fois de suite. Le résultat final est-il exactement 10,0 ?

total = 0.0
for i in range(1000):
    total += 0.01
print(total)
print(total == 10.0)

g. Modifier le programme pour obtenir un résultat exact en utilisant des entiers (compter en centimes au lieu d'euros).

Partie C - L'affaire du missile Patriot (1991)

Pendant la guerre du Golfe, un missile Patriot a raté sa cible à cause d'une erreur de flottants.

h. Le système mesurait le temps en dixièmes de seconde avec un compteur entier, puis le convertissait en secondes en multipliant par 0,1. Pourquoi cette conversion introduit-elle une erreur ?

i. Le système avait fonctionné pendant 100 heures. Sachant que l'erreur sur 0,1 en binaire est d'environ 9,5 × 10⁻⁸ seconde par dixième de seconde, calculer l'erreur totale accumulée après 100 heures (en secondes).

j. Un missile Scud se déplace à environ 1 676 m/s. Quelle distance parcourt-il pendant ce décalage temporel ?

Correction

a. 0.30000000000000004 (inexact)

b. 0.9999999999999999 (inexact, pas exactement 1.0)

c. 0.9999999999999999 (inexact, identique)

d. 0.30000000000000004 (inexact)

e. 0.75 (exact)

Les résultats exacts correspondent aux nombres dont le dénominateur est une puissance de 2 : 0,5 = 1/2 et 0,25 = 1/4. Leur somme 0,75 = 3/4 est aussi exacte.

f.

total = 0.0
for i in range(1000):
    total += 0.01
print(total)       # 9.999999999999831
print(total == 10.0)  # False
Le résultat est environ 9,9999999999998, pas 10,0.

g.

total_centimes = 0
for i in range(1000):
    total_centimes += 1
total_euros = total_centimes / 100
print(total_euros)       # 10.0
print(total_euros == 10.0)  # True

h. 0,1 n'a pas de représentation binaire exacte (c'est 0,000110011... avec une période infinie). Chaque multiplication par 0,1 introduit une petite erreur d'arrondi.

i. 100 heures = 100 × 3 600 = 360 000 secondes = 3 600 000 dixièmes de seconde. Erreur totale = 3 600 000 × 9,5 × 10⁻⁸ = 0,342 seconde.

j. Distance = 1 676 × 0,342 = 573 mètres. Le missile cherchait sa cible 573 mètres trop loin. C'est ce qui s'est passé le 25 février 1991 à Dhahran (Arabie saoudite) : 28 soldats ont été tués.


🎯 Projet final - Le convertisseur universel

Objectif

Concevoir un programme Python complet qui regroupe toutes les notions du thème : conversions de bases, complément à 2, analyse de flottants et encodage de textes.

Cahier des charges

Écrire un programme Python interactif qui propose un menu avec les fonctionnalités suivantes :

=== Convertisseur universel ===
1. Convertir un entier (décimal ↔ binaire ↔ hexadécimal)
2. Coder/décoder un entier en complément à 2 (8, 16 ou 32 bits)
3. Analyser un nombre flottant (afficher la représentation exacte)
4. Encoder/décoder un texte (codes ASCII/Unicode)
5. Quitter

Partie A - Conversions de bases

a. Écrire une fonction dec_vers_bin(n) qui convertit un entier positif en binaire sans utiliser bin(). Elle renvoie une chaîne de caractères.

b. Écrire une fonction dec_vers_hex(n) qui convertit un entier positif en hexadécimal sans utiliser hex().

c. Écrire une fonction bin_vers_dec(b) qui prend une chaîne binaire et renvoie l'entier décimal correspondant sans utiliser int(b, 2).

Partie B - Complément à 2

d. Écrire une fonction complement_a_2(n, bits) qui code un entier relatif en complément à 2 sur le nombre de bits donné. Lever une erreur si le nombre ne tient pas sur le nombre de bits choisi.

e. Écrire une fonction decode_complement(binaire) qui prend une chaîne en complément à 2 et renvoie la valeur décimale.

Partie C - Analyse de flottants

f. Écrire une fonction analyse_flottant(x) qui affiche :

  • La valeur entrée
  • La valeur réellement stockée (avec 20 décimales : f"{x:.20f}")
  • L'erreur d'arrondi par rapport à la valeur stockée
  • Si le nombre est exact ou non en binaire

Partie D - Encodage de textes

g. Écrire une fonction texte_vers_codes(texte) qui renvoie la liste des codes Unicode de chaque caractère.

h. Écrire une fonction codes_vers_texte(codes) qui reconstruit le texte à partir d'une liste de codes.

Partie E - Le menu interactif

i. Assembler le tout dans un programme avec un menu en boucle.

Correction
def dec_vers_bin(n):
    if n == 0:
        return "0"
    bits = ""
    while n > 0:
        bits = str(n % 2) + bits
        n = n // 2
    return bits

def dec_vers_hex(n):
    if n == 0:
        return "0"
    symboles = "0123456789ABCDEF"
    resultat = ""
    while n > 0:
        resultat = symboles[n % 16] + resultat
        n = n // 16
    return resultat

def bin_vers_dec(b):
    resultat = 0
    for bit in b:
        resultat = resultat * 2 + int(bit)
    return resultat

def complement_a_2(n, bits):
    min_val = -(2 ** (bits - 1))
    max_val = 2 ** (bits - 1) - 1
    if n < min_val or n > max_val:
        raise ValueError(f"{n} ne tient pas sur {bits} bits "
                         f"(intervalle [{min_val}, {max_val}])")
    if n >= 0:
        binaire = dec_vers_bin(n)
        return binaire.zfill(bits)
    else:
        positif = dec_vers_bin(-n).zfill(bits)
        inverse = "".join("1" if b == "0" else "0" for b in positif)
        # Ajouter 1
        resultat = list(inverse)
        retenue = 1
        for i in range(len(resultat) - 1, -1, -1):
            somme = int(resultat[i]) + retenue
            resultat[i] = str(somme % 2)
            retenue = somme // 2
        return "".join(resultat)

def decode_complement(binaire):
    if binaire[0] == "0":
        return bin_vers_dec(binaire)
    else:
        inverse = "".join("1" if b == "0" else "0" for b in binaire)
        return -(bin_vers_dec(inverse) + 1)

def analyse_flottant(x):
    print(f"  Valeur entree       : {x}")
    print(f"  Valeur stockee      : {x:.20f}")
    from decimal import Decimal
    exact = Decimal(x)
    attendu = Decimal(str(x))
    erreur = abs(exact - attendu)
    print(f"  Erreur d'arrondi    : {erreur}")
    print(f"  Representation exacte : {'Oui' if erreur == 0 else 'Non'}")

def texte_vers_codes(texte):
    return [ord(c) for c in texte]

def codes_vers_texte(codes):
    return "".join(chr(c) for c in codes)

def menu():
    while True:
        print("\n=== Convertisseur universel ===")
        print("1. Convertir un entier (decimal <-> binaire <-> hexadecimal)")
        print("2. Coder/decoder un entier en complement a 2")
        print("3. Analyser un nombre flottant")
        print("4. Encoder/decoder un texte (codes ASCII/Unicode)")
        print("5. Quitter")

        choix = input("\nVotre choix : ")

        if choix == "1":
            n = int(input("Entier positif : "))
            print(f"  Binaire      : {dec_vers_bin(n)}")
            print(f"  Hexadecimal  : {dec_vers_hex(n)}")
            print(f"  Decimal      : {n}")

        elif choix == "2":
            n = int(input("Entier relatif : "))
            bits = int(input("Nombre de bits (8, 16 ou 32) : "))
            try:
                code = complement_a_2(n, bits)
                print(f"  Complement a 2 : {code}")
                print(f"  Verification   : {decode_complement(code)}")
            except ValueError as e:
                print(f"  Erreur : {e}")

        elif choix == "3":
            x = float(input("Nombre a virgule : "))
            analyse_flottant(x)

        elif choix == "4":
            action = input("(E)ncoder ou (D)ecoder ? ").upper()
            if action == "E":
                texte = input("Texte : ")
                codes = texte_vers_codes(texte)
                print(f"  Codes Unicode : {codes}")
            elif action == "D":
                saisie = input("Codes separes par des espaces : ")
                codes = [int(c) for c in saisie.split()]
                print(f"  Texte : {codes_vers_texte(codes)}")

        elif choix == "5":
            print("Au revoir !")
            break

Exemple d'exécution :

=== Convertisseur universel ===
1. Convertir un entier (decimal <-> binaire <-> hexadecimal)

Votre choix : 1
Entier positif : 255
  Binaire      : 11111111
  Hexadecimal  : FF
  Decimal      : 255

Votre choix : 2
Entier relatif : -42
Nombre de bits (8, 16 ou 32) : 8
  Complement a 2 : 11010110
  Verification   : -42

Votre choix : 3
Nombre a virgule : 0.1
  Valeur entree       : 0.1
  Valeur stockee      : 0.10000000000000000555
  Erreur d'arrondi    : 5.55E-18
  Representation exacte : Non