{
  "chapter": {
    "id": "representation-reels",
    "level": "premiere",
    "theme": "Représentation des données",
    "title": "Représentation des réels",
    "description": "Représentation des nombres réels en machine, virgule fixe et\nvirgule flottante, norme IEEE 754, précision et erreurs\nd'arrondi, conséquences pratiques sur les calculs.",
    "prerequisites": [],
    "references": []
  },
  "questions": [
    {
      "id": "q01",
      "difficulty": 1,
      "skills": [
        "definition",
        "type"
      ],
      "title": "Type des réels en Python",
      "statement": "Quel est le type Python utilisé pour représenter les\nnombres à virgule ?",
      "options": [
        {
          "text": "`number`",
          "correct": false,
          "feedback": "Erreur : `number` n'est pas un type Python standard.\n"
        },
        {
          "text": "`float`",
          "correct": true,
          "feedback": "Bonne réponse : `float` (« nombre à virgule\nflottante ») est le type Python pour les nombres\nréels approchés. Par défaut, ils sont codés sur $64$\nbits selon la norme IEEE $754$.\n"
        },
        {
          "text": "`int`",
          "correct": false,
          "feedback": "Erreur : `int` est le type des entiers en Python.\n"
        },
        {
          "text": "`real`",
          "correct": false,
          "feedback": "Erreur : `real` n'existe pas en Python (mais existe\ndans certains autres langages comme Pascal).\n"
        }
      ],
      "explanation": "Les nombres flottants sont **approchés**. Pour des\ncalculs en précision arbitraire, Python propose le\nmodule `decimal` (calculs en base $10$ exacts) ou\n`fractions` (rationnels exacts)."
    },
    {
      "id": "q02",
      "difficulty": 1,
      "skills": [
        "virgule-flottante"
      ],
      "title": "Notation scientifique",
      "statement": "L'écriture **scientifique** d'un nombre réel sépare un\nréel en :",
      "options": [
        {
          "text": "Une fraction irréductible",
          "correct": false,
          "feedback": "Une fraction irréductible\n(comme $\\dfrac{3}{7}$) est\nune autre façon d'écrire\nun rationnel, mais ce n'est\npas la notation scientifique\nen base deux utilisée par\nles flottants.\n"
        },
        {
          "text": "Une partie entière et une partie décimale",
          "correct": false,
          "feedback": "Erreur : c'est plutôt l'écriture habituelle en base\n$10$. La notation scientifique factorise en mantisse\net exposant.\n"
        },
        {
          "text": "Un signe et une valeur absolue",
          "correct": false,
          "feedback": "Erreur : c'est une décomposition différente, qui\nn'est pas spécifiquement scientifique.\n"
        },
        {
          "text": "Une mantisse (entre $1$ et $10$) et un exposant entier de $10$",
          "correct": true,
          "feedback": "Bonne réponse : par exemple, $345{,}67 = 3{,}4567 \\times 10^2$.\nLa mantisse est $3{,}4567$, l'exposant est $2$.\nC'est l'idée de base de la représentation à virgule\nflottante (en base $2$ pour les ordinateurs).\n"
        }
      ],
      "explanation": "En base $2$ (binaire), la notation scientifique s'écrit\n$m \\times 2^e$, avec une mantisse $m$ entre $1$ et $2$\net un exposant $e$ entier. C'est exactement ce que fait\nla norme IEEE $754$."
    },
    {
      "id": "q03",
      "difficulty": 1,
      "skills": [
        "ieee754"
      ],
      "title": "Norme IEEE 754",
      "statement": "Que définit la norme **IEEE $754$** ?",
      "options": [
        {
          "text": "La représentation binaire des nombres à virgule flottante (signe, exposant, mantisse)",
          "correct": true,
          "feedback": "Bonne réponse : la norme IEEE $754$ ($1985$, révisée\nen $2008$ et $2019$) standardise les formats de\nflottants : simple précision (`float`, $32$ bits),\ndouble précision (`double`, $64$ bits) et plus.\nPratiquement tous les processeurs respectent cette\nnorme.\n"
        },
        {
          "text": "La connectique des câbles réseau",
          "correct": false,
          "feedback": "Erreur : aucun rapport. Les normes IEEE de connectique\nsont différentes (par exemple IEEE $802.3$ pour\nEthernet).\n"
        },
        {
          "text": "Le format des adresses IP",
          "correct": false,
          "feedback": "Erreur : c'est plutôt la RFC $791$ (et autres) qui\ndéfinit les adresses IP. IEEE $754$ concerne les\nréels.\n"
        },
        {
          "text": "Le format des fichiers PDF",
          "correct": false,
          "feedback": "Le format PDF est défini\npar la spécification ISO\n$32000$. Il n'a aucun lien\navec la norme IEEE $754$,\nqui concerne uniquement\nles nombres flottants.\n"
        }
      ],
      "explanation": "Avant IEEE $754$, chaque constructeur avait son propre\nformat flottant, un même calcul pouvait donner des\nrésultats différents selon la machine. La norme a\nuniformisé tout cela."
    },
    {
      "id": "q04",
      "difficulty": 1,
      "skills": [
        "precision"
      ],
      "title": "Approximation des réels",
      "statement": "Pourquoi les réels stockés en machine sont-ils en général\ndes **approximations** plutôt que des valeurs exactes ?",
      "options": [
        {
          "text": "Parce qu'il y a une infinité de nombres réels mais une mémoire finie",
          "correct": true,
          "feedback": "Bonne réponse : on ne peut représenter qu'un nombre\nfini de valeurs en mémoire finie. La plupart des\nréels (par exemple $\\pi$, $\\sqrt{2}$) doivent être\napprochés. Même certains nombres « simples » comme\n$0{,}1$ n'ont pas de représentation binaire finie.\n"
        },
        {
          "text": "Parce que les ordinateurs sont mal conçus",
          "correct": false,
          "feedback": "Erreur : ce n'est pas un défaut de conception, c'est\nune nécessité mathématique.\n"
        },
        {
          "text": "Parce qu'il faut moins de mémoire",
          "correct": false,
          "feedback": "Erreur : c'est pour des raisons mathématiques\nfondamentales, pas seulement d'optimisation.\n"
        },
        {
          "text": "Parce que les flottants sont plus rapides que les entiers",
          "correct": false,
          "feedback": "Erreur : les flottants sont en réalité plus lents\nque les entiers sur la plupart des processeurs.\n"
        }
      ],
      "explanation": "C'est une limite **fondamentale** : aucun ordinateur,\nquelle que soit sa puissance, ne peut représenter\nexactement tous les réels. Il faut donc choisir un\ncompromis sur la précision et l'étendue."
    },
    {
      "id": "q05",
      "difficulty": 1,
      "skills": [
        "erreur-arrondi"
      ],
      "title": "Calcul flottant en Python",
      "statement": "Que renvoie l'expression Python `0.1 + 0.2` ?",
      "options": [
        {
          "text": "Une erreur Python",
          "correct": false,
          "feedback": "Erreur : aucune erreur, le calcul est valide. Mais\nson résultat n'est pas exactement $0{,}3$.\n"
        },
        {
          "text": "Exactement $0{,}3$",
          "correct": false,
          "feedback": "Erreur : $0{,}1$ et $0{,}2$ n'ont pas de\nreprésentation binaire **finie** (comme $1/3$ en\nbase $10$). Leur somme contient donc une erreur\nd'arrondi.\n"
        },
        {
          "text": "$0{,}29999\\ldots$ (sans aucune erreur)",
          "correct": false,
          "feedback": "Erreur : la valeur exacte stockée est légèrement\n**supérieure** à $0{,}3$, pas inférieure.\n"
        },
        {
          "text": "Une valeur très proche de $0{,}3$, mais avec une petite erreur d'arrondi (par exemple $0{,}30000000000000004$)",
          "correct": true,
          "feedback": "Bonne réponse : c'est l'exemple emblématique des\npièges du calcul flottant. Pour comparer des\nflottants, on utilise typiquement\n`abs(a - b) < epsilon`.\n"
        }
      ],
      "explanation": "$0{,}1$ en binaire vaut\n$0{,}0001100110011\\ldots$ (motif périodique infini).\nL'arrondi à un nombre fini de bits crée une petite\nerreur, qui se propage dans les calculs."
    },
    {
      "id": "q06",
      "difficulty": 1,
      "skills": [
        "comparaison-flottants"
      ],
      "title": "Comparer deux flottants",
      "statement": "Pour tester si deux flottants `a` et `b` sont « égaux »\nen Python, la bonne pratique est :",
      "options": [
        {
          "text": "`a == b`",
          "correct": false,
          "feedback": "Erreur : à cause des erreurs d'arrondi, deux\nflottants qui devraient être égaux peuvent\nlégèrement différer. `==` est trop strict.\n"
        },
        {
          "text": "`int(a) == int(b)`",
          "correct": false,
          "feedback": "Erreur : on perd la partie décimale. Et de plus, le\ntest est trop large (deux flottants très différents\npeuvent donner le même entier après troncature).\n"
        },
        {
          "text": "`abs(a - b) < epsilon` avec `epsilon` petit (par exemple $10^{-9}$)",
          "correct": true,
          "feedback": "Bonne réponse : on compare à une **tolérance**\narbitraire. Le choix d'`epsilon` dépend du contexte.\nPython propose aussi `math.isclose(a, b)` avec des\ntolérances par défaut sensées.\n"
        },
        {
          "text": "`a is b`",
          "correct": false,
          "feedback": "Erreur : `is` teste l'identité (même objet en\nmémoire), pas l'égalité numérique. Ne fonctionnera\npresque jamais avec des flottants.\n"
        }
      ],
      "explanation": "Cette précaution est essentielle dans tous les calculs\nscientifiques. Les comparaisons strictes de flottants\nsont une source classique de bugs subtils."
    },
    {
      "id": "q07",
      "difficulty": 1,
      "skills": [
        "virgule-fixe"
      ],
      "title": "Virgule fixe",
      "statement": "Quelle est la différence entre une représentation à\n**virgule fixe** et une représentation à **virgule\nflottante** ?",
      "options": [
        {
          "text": "La virgule fixe a un nombre de chiffres fractionnaires constant ; la virgule flottante a une précision relative",
          "correct": true,
          "feedback": "Bonne réponse : avec virgule fixe, par exemple\ndeux décimales, on peut représenter $0{,}01$ à\n$9999{,}99$. Avec virgule flottante, l'exposant\npermet d'aller de très petit ($10^{-300}$) à très\ngrand ($10^{300}$), au prix d'une précision relative.\n"
        },
        {
          "text": "La virgule fixe n'existe que sur les vieux ordinateurs",
          "correct": false,
          "feedback": "Erreur : la virgule fixe est encore utilisée\naujourd'hui (par exemple en finance pour des\nmontants en centimes).\n"
        },
        {
          "text": "Aucune différence en pratique",
          "correct": false,
          "feedback": "Erreur : les différences sont importantes,\nnotamment pour des applications spécifiques.\n"
        },
        {
          "text": "La virgule fixe est plus précise pour les très grands nombres",
          "correct": false,
          "feedback": "Erreur : c'est plutôt la virgule flottante qui gère\nmieux les très grands ou très petits nombres\n(grâce à l'exposant variable).\n"
        }
      ],
      "explanation": "Cas typique de virgule fixe : la finance, où on\nmanipule des montants à deux décimales, et on veut\néviter les erreurs d'arrondi sur l'argent. On stocke\nalors les montants en centimes (entiers)."
    },
    {
      "id": "q08",
      "difficulty": 1,
      "skills": [
        "taille"
      ],
      "title": "Taille d'un float Python",
      "statement": "En Python, sur combien de bits est stocké un `float` ?",
      "options": [
        {
          "text": "$128$ bits",
          "correct": false,
          "feedback": "Erreur : la quadruple précision ($128$ bits) existe\nmais n'est pas le standard de Python.\n"
        },
        {
          "text": "$64$ bits",
          "correct": true,
          "feedback": "Bonne réponse : Python utilise par défaut la double\nprécision IEEE $754$, soit $64$ bits ($1$ pour le\nsigne, $11$ pour l'exposant, $52$ pour la mantisse).\nCela donne environ $15$ à $17$ chiffres décimaux\nsignificatifs.\n"
        },
        {
          "text": "$8$ bits",
          "correct": false,
          "feedback": "Erreur : trop peu pour représenter une plage utile\nde réels.\n"
        },
        {
          "text": "$32$ bits",
          "correct": false,
          "feedback": "Erreur : c'est la **simple précision** (le type\n`float` du langage C). Python utilise par défaut la\ndouble précision.\n"
        }
      ],
      "explanation": "Pour des besoins de précision supérieure, Python\npropose le module `decimal` (précision arbitraire en\nbase $10$) et `fractions` (rationnels exacts)."
    },
    {
      "id": "q09",
      "difficulty": 1,
      "skills": [
        "zero",
        "special"
      ],
      "title": "Valeurs spéciales IEEE 754",
      "statement": "La norme IEEE $754$ définit quelques valeurs spéciales\nen plus des nombres réguliers. Lesquelles ?",
      "options": [
        {
          "text": "Aucune valeur spéciale",
          "correct": false,
          "feedback": "Erreur : les valeurs spéciales sont une partie\nessentielle de la norme.\n"
        },
        {
          "text": "$+\\infty$, $-\\infty$, et NaN (« Not a Number »)",
          "correct": true,
          "feedback": "Bonne réponse : ces valeurs gèrent les opérations\nextrêmes. $1/0$ donne $+\\infty$, $\\sqrt{-1}$ ou\n$0/0$ donnent NaN. Cela évite les plantages et\npermet des calculs plus robustes.\n"
        },
        {
          "text": "$\\pi$, $e$, $\\sqrt{2}$",
          "correct": false,
          "feedback": "Erreur : ces nombres sont représentés comme tout\nautre flottant, par approximation. Ils n'ont pas de\nvaleur spéciale dédiée.\n"
        },
        {
          "text": "Vrai et Faux",
          "correct": false,
          "feedback": "Erreur : ce sont des valeurs **booléennes**, pas\nflottantes.\n"
        }
      ],
      "explanation": "En Python : `float('inf')`, `float('-inf')`,\n`float('nan')`. Le test `nan == nan` renvoie `False`\n(selon la norme), ce qui peut surprendre."
    },
    {
      "id": "q10",
      "difficulty": 1,
      "skills": [
        "signe",
        "exposant",
        "mantisse"
      ],
      "title": "Composantes d'un flottant IEEE 754",
      "statement": "Quels sont les **trois champs** qui composent la\nreprésentation IEEE $754$ d'un nombre flottant ?",
      "options": [
        {
          "text": "Partie entière, partie décimale, partie complexe",
          "correct": false,
          "feedback": "Erreur : ce serait une décomposition mathématique,\npas la représentation IEEE $754$.\n"
        },
        {
          "text": "Numérateur, dénominateur, exposant",
          "correct": false,
          "feedback": "Erreur : aucun rapport avec une fraction. La\nmantisse n'est pas un dénominateur.\n"
        },
        {
          "text": "Octets supérieurs, médians, inférieurs",
          "correct": false,
          "feedback": "Erreur : c'est une découpe physique, pas la\ndécomposition logique.\n"
        },
        {
          "text": "Bit de signe, exposant biaisé, mantisse (fraction)",
          "correct": true,
          "feedback": "Bonne réponse : le bit de signe ($0$ pour positif,\n$1$ pour négatif), l'exposant codé avec un biais\n(pour permettre des exposants négatifs sans bit de\nsigne séparé), et la mantisse normalisée.\n"
        }
      ],
      "explanation": "Pour un flottant $64$ bits (double précision) :\n$1$ bit de signe + $11$ bits d'exposant +\n$52$ bits de mantisse = $64$ bits."
    },
    {
      "id": "q11",
      "difficulty": 2,
      "skills": [
        "calcul",
        "erreur"
      ],
      "title": "Erreur d'arrondi cumulative",
      "statement": "Que peut-il se passer si on additionne plusieurs millions\nde petits flottants entre eux ?",
      "options": [
        {
          "text": "Le résultat est exact, comme une somme d'entiers",
          "correct": false,
          "feedback": "Erreur : chaque addition introduit une petite erreur\nd'arrondi. Sur des millions d'opérations, ces\nerreurs s'accumulent.\n"
        },
        {
          "text": "Le calcul devient infiniment lent",
          "correct": false,
          "feedback": "Erreur : la vitesse n'est pas l'enjeu. C'est la\nprécision qui se dégrade.\n"
        },
        {
          "text": "Python lève une erreur de précision",
          "correct": false,
          "feedback": "Erreur : aucune erreur n'est levée. Les calculs\nflottants sont silencieusement approximatifs.\n"
        },
        {
          "text": "Les erreurs d'arrondi peuvent s'accumuler et donner un résultat sensiblement différent du résultat mathématique exact",
          "correct": true,
          "feedback": "Bonne réponse : c'est un piège classique en calcul\nscientifique. Pour minimiser les erreurs, on peut\nadditionner par ordre croissant (somme de Kahan)\nou utiliser une précision étendue.\n"
        }
      ],
      "explanation": "Un exemple frappant : `sum([0.1] * 10)` en Python ne\ndonne pas exactement $1{,}0$, à cause des erreurs\ncumulées. Pour des calculs financiers, on utilise\n`decimal` ; pour des sommes scientifiques, des\nalgorithmes spécialisés."
    },
    {
      "id": "q12",
      "difficulty": 2,
      "skills": [
        "overflow"
      ],
      "title": "Dépassement",
      "statement": "Que renvoie en Python l'opération `1e308 * 10` (où\n`1e308` désigne $10^{308}$) ?",
      "options": [
        {
          "text": "$10^{309}$",
          "correct": false,
          "feedback": "Erreur : $10^{309}$ dépasse la plage des doubles\nprécision (limite vers $1{,}8 \\times 10^{308}$).\nLe résultat est donc une valeur spéciale.\n"
        },
        {
          "text": "`inf`",
          "correct": true,
          "feedback": "Bonne réponse : on dépasse le maximum représentable\nen double précision. La norme IEEE $754$ traduit\ncela par `+inf` (infini positif). C'est un\ndépassement (*overflow*) flottant.\n"
        },
        {
          "text": "Une erreur de Python",
          "correct": false,
          "feedback": "Erreur : aucune erreur, c'est un comportement\ndéfini par la norme.\n"
        },
        {
          "text": "$0$",
          "correct": false,
          "feedback": "Erreur : ce serait un *underflow* (sous-dépassement\nvers zéro), pas un dépassement par le haut.\n"
        }
      ],
      "explanation": "Le fait que les calculs flottants ne plantent pas, mais\ndonnent des valeurs spéciales (`inf`, `nan`), permet de\npoursuivre les calculs sans interruption. Mais\nattention à ne pas oublier de vérifier ces valeurs si\nelles peuvent affecter le résultat."
    },
    {
      "id": "q13",
      "difficulty": 2,
      "skills": [
        "precision"
      ],
      "title": "Précision en double précision",
      "statement": "Combien de chiffres décimaux significatifs un flottant\nen **double précision** ($64$ bits) peut-il représenter\nde manière fiable ?",
      "options": [
        {
          "text": "Une infinité",
          "correct": false,
          "feedback": "Erreur : aucune représentation finie ne peut donner\nune infinité de chiffres exacts.\n"
        },
        {
          "text": "Environ $50$",
          "correct": false,
          "feedback": "Erreur : très excessif. La double précision ne\ndépasse pas $17$ chiffres décimaux fiables.\n"
        },
        {
          "text": "Environ $15$ à $17$",
          "correct": true,
          "feedback": "Bonne réponse : avec $52$ bits de mantisse, on a\n$\\log_{10}(2^{52}) \\approx 15{,}65$ chiffres\nsignificatifs. Au-delà, on n'a plus aucune garantie\nde précision.\n"
        },
        {
          "text": "Environ $7$",
          "correct": false,
          "feedback": "Erreur : c'est la précision de la **simple** précision\n($32$ bits, mantisse $23$ bits). En double précision,\non a plus.\n"
        }
      ],
      "explanation": "Pour des besoins supérieurs (cosmologie, cryptographie,\nmathématiques précises), on utilise des bibliothèques\nde précision arbitraire (mpfr, decimal, etc.) qui\nacceptent un coût de performance."
    },
    {
      "id": "q14",
      "difficulty": 2,
      "skills": [
        "comparaison-isclose"
      ],
      "title": "math.isclose",
      "statement": "En Python, la fonction `math.isclose(a, b)` :",
      "options": [
        {
          "text": "Convertit `a` et `b` en chaînes de caractères",
          "correct": false,
          "feedback": "Erreur : aucune conversion en chaîne.\n"
        },
        {
          "text": "Compare deux flottants en tolérant une petite différence relative et/ou absolue",
          "correct": true,
          "feedback": "Bonne réponse : `math.isclose(a, b)` utilise par\ndéfaut une tolérance relative de $10^{-9}$ et une\ntolérance absolue de $0$. On peut les ajuster avec\n`rel_tol` et `abs_tol`.\n"
        },
        {
          "text": "Renvoie toujours `True`",
          "correct": false,
          "feedback": "Erreur : elle teste vraiment l'égalité approximative.\n"
        },
        {
          "text": "Lève une erreur si les nombres ne sont pas exactement égaux",
          "correct": false,
          "feedback": "Erreur : c'est plutôt une fonction tolérante.\n"
        }
      ],
      "explanation": "Cette fonction (introduite en Python $3{,}5$) est la\nbonne pratique recommandée pour comparer des flottants.\nElle est plus robuste que `abs(a - b) < epsilon` car\nelle prend en compte l'**ordre de grandeur** des\nnombres comparés."
    },
    {
      "id": "q15",
      "difficulty": 2,
      "skills": [
        "calcul-financier"
      ],
      "title": "Calcul financier",
      "statement": "Pour un calcul financier (additionner des centimes),\nquel choix est le plus prudent en Python ?",
      "options": [
        {
          "text": "Utiliser des `float`",
          "correct": false,
          "feedback": "Erreur : les flottants accumulent des erreurs\nd'arrondi qui peuvent fausser des montants en\ncentimes. Mauvaise pratique financière.\n"
        },
        {
          "text": "Utiliser des nombres complexes",
          "correct": false,
          "feedback": "Erreur : aucun rapport avec les nombres complexes.\n"
        },
        {
          "text": "Utiliser le module `decimal` ou des entiers représentant des centimes",
          "correct": true,
          "feedback": "Bonne réponse : le module `decimal` calcule en\nbase $10$ exactement (pas d'erreur d'arrondi pour\n$0{,}1$). Alternative : stocker les montants en\ncentimes (entiers), sans virgule.\n"
        },
        {
          "text": "Utiliser des chaînes de caractères",
          "correct": false,
          "feedback": "Erreur : on ne peut pas faire d'arithmétique\ndirectement sur des chaînes en Python.\n"
        }
      ],
      "explanation": "Les régulations financières interdisent souvent\nl'usage de `float` pour des montants. La précision\ndoit être garantie au centième. Les bibliothèques\nfinancières sérieuses utilisent toujours `decimal` ou\nl'équivalent."
    },
    {
      "id": "q16",
      "difficulty": 2,
      "skills": [
        "conversion"
      ],
      "title": "Conversion entier vers flottant",
      "statement": "En Python, l'instruction `float(7)` renvoie :",
      "options": [
        {
          "text": "`7` (entier inchangé)",
          "correct": false,
          "feedback": "Erreur : la fonction `float` change le type. Le\nrésultat est `7.0`, qui est un flottant.\n"
        },
        {
          "text": "`7.0` (flottant)",
          "correct": true,
          "feedback": "Bonne réponse : la conversion d'un entier en\nflottant ajoute « .0 ». Le type passe de `int` à\n`float`.\n"
        },
        {
          "text": "Une erreur",
          "correct": false,
          "feedback": "Erreur : aucune erreur, c'est une conversion\nstandard.\n"
        },
        {
          "text": "`'7'` (chaîne de caractères)",
          "correct": false,
          "feedback": "Erreur : `float()` convertit en flottant, pas en\nchaîne. Pour une chaîne, on utiliserait `str(7)`.\n"
        }
      ],
      "explanation": "Inversement, `int(7.9)` renvoie $7$ (troncature, pas\narrondi). Pour arrondir, on utilise `round(7.9)` qui\nrenvoie $8$."
    },
    {
      "id": "q17",
      "difficulty": 2,
      "skills": [
        "perte-significativite"
      ],
      "title": "Perte de signification",
      "statement": "Pourquoi `(1e16 + 1) - 1e16` donne-t-il $0$ en Python\nau lieu de $1$ ?",
      "options": [
        {
          "text": "Parce que $1$ est négligeable face à $10^{16}$, la mantisse ne peut pas représenter cette différence avec sa précision limitée",
          "correct": true,
          "feedback": "Bonne réponse : la double précision a environ $16$\nchiffres significatifs. Quand on ajoute $1$ à\n$10^{16}$, le $1$ est « écrasé » par les erreurs\nd'arrondi. C'est la **perte de signification**\n(*loss of significance*).\n"
        },
        {
          "text": "Parce que Python ne sait pas additionner",
          "correct": false,
          "feedback": "Erreur : Python sait additionner. La limitation\nvient du format de représentation des flottants.\n"
        },
        {
          "text": "Parce que les nombres trop grands sont arrondis à zéro",
          "correct": false,
          "feedback": "Erreur : ce n'est pas l'arrondi à zéro, c'est plus\nsubtil : c'est la précision relative limitée.\n"
        },
        {
          "text": "C'est un bug de Python",
          "correct": false,
          "feedback": "Erreur : ce n'est pas un bug, c'est un comportement\nattendu et défini par IEEE $754$.\n"
        }
      ],
      "explanation": "Pour éviter ce piège : reformuler les calculs pour\néviter de soustraire des nombres très proches, ou\npasser en précision étendue. C'est un problème\nclassique du calcul numérique scientifique."
    },
    {
      "id": "q18",
      "difficulty": 2,
      "skills": [
        "normalisation"
      ],
      "title": "Forme normalisée",
      "statement": "En IEEE $754$, un flottant **normalisé** s'écrit dans la\nforme :",
      "options": [
        {
          "text": "$0{,}m \\times 2^e$ avec $m$ quelconque",
          "correct": false,
          "feedback": "Erreur : la forme normalisée a une mantisse\ncomprise entre $1$ et $2$, pas entre $0$ et $1$.\n"
        },
        {
          "text": "$1{,}m \\times 2^e$ avec un bit implicite à $1$ devant la mantisse",
          "correct": true,
          "feedback": "Bonne réponse : la mantisse est toujours au format\n$1{,}\\text{xxx}$ en binaire (puisque le premier bit\nd'un nombre non nul vaut $1$). On stocke seulement\nla partie après la virgule, gagnant ainsi un bit\nde précision « gratuit ».\n"
        },
        {
          "text": "$m \\times 10^e$ avec $m$ et $e$ entiers",
          "correct": false,
          "feedback": "Erreur : la base est $2$, pas $10$. Et la mantisse\nn'est pas toujours entière.\n"
        },
        {
          "text": "$m + e$ (somme)",
          "correct": false,
          "feedback": "Erreur : la mantisse et l'exposant ne s'additionnent\npas, ils se combinent par produit ($m \\times 2^e$).\n"
        }
      ],
      "explanation": "Cette astuce du « bit implicite » offre un bit gratuit\ndans la mantisse. Pour les très petits nombres (proches\nde zéro), on a aussi des nombres **dénormalisés** où\ncette convention ne s'applique pas, permettant une\nprécision graduelle vers zéro."
    },
    {
      "id": "q19",
      "difficulty": 2,
      "skills": [
        "associativite"
      ],
      "title": "Non-associativité de l'addition flottante",
      "statement": "En arithmétique flottante, l'addition est-elle toujours\n**associative** (c'est-à-dire $(a + b) + c = a + (b + c)$) ?",
      "options": [
        {
          "text": "Cela dépend du système d'exploitation",
          "correct": false,
          "feedback": "Erreur : pas de lien avec le système.\n"
        },
        {
          "text": "Cela dépend du langage de programmation",
          "correct": false,
          "feedback": "Erreur : c'est une propriété de la norme IEEE $754$,\nindépendante du langage.\n"
        },
        {
          "text": "Non, l'ordre des additions peut changer le résultat à cause des arrondis",
          "correct": true,
          "feedback": "Bonne réponse : par exemple,\n`(1e16 + 1) - 1e16 = 0` mais `(1e16 - 1e16) + 1 = 1`.\nCe détail est crucial en programmation parallèle :\nadditionner dans un ordre différent peut donner un\nrésultat différent.\n"
        },
        {
          "text": "Oui, comme pour les entiers",
          "correct": false,
          "feedback": "Erreur : c'est une croyance répandue mais fausse !\nÀ cause des arrondis, l'ordre des additions peut\nchanger le résultat.\n"
        }
      ],
      "explanation": "Cette non-associativité a des implications concrètes :\nen parallélisme, des sommes massives peuvent donner\ndes résultats légèrement différents selon l'ordre de\nréduction. En science du calcul, on cherche des\nalgorithmes qui minimisent cette dépendance."
    },
    {
      "id": "q20",
      "difficulty": 2,
      "skills": [
        "decimal-vs-binaire"
      ],
      "title": "Décimal vs binaire",
      "statement": "Pourquoi $0{,}5$ a une représentation binaire **exacte**,\nmais pas $0{,}1$ ?",
      "options": [
        {
          "text": "Parce que $0{,}5$ est plus grand que $0{,}1$",
          "correct": false,
          "feedback": "Erreur : aucune raison liée à la taille relative.\n"
        },
        {
          "text": "Parce que $0{,}5$ est utilisé plus souvent",
          "correct": false,
          "feedback": "Erreur : la fréquence d'usage n'a rien à voir avec\nla représentabilité.\n"
        },
        {
          "text": "Parce que $0{,}5$ a un seul chiffre, $0{,}1$ aussi",
          "correct": false,
          "feedback": "Erreur : c'est en base $10$. En binaire, la\nlongueur des deux écritures est très différente.\n"
        },
        {
          "text": "Parce que $0{,}5 = 1/2 = 2^{-1}$ est une puissance de $2$, alors que $0{,}1 = 1/10$ ne l'est pas et donne un développement périodique en binaire",
          "correct": true,
          "feedback": "Bonne réponse : en base $2$, seules les fractions\ndont le dénominateur est une puissance de $2$\n(ou des sommes de telles fractions) ont une\nreprésentation **finie**. Pour $1/10$, on obtient\n$0{,}0001100110011\\ldots_2$, périodique infini.\n"
        }
      ],
      "explanation": "C'est l'analogue de $1/3 = 0{,}333\\ldots$ en base $10$.\nToute base privilégie certaines fractions et en\ndésavantage d'autres. Le calcul en base $10$ (`decimal`)\nrésout ce problème pour les nombres décimaux humains."
    },
    {
      "id": "q21",
      "difficulty": 3,
      "skills": [
        "biais"
      ],
      "title": "Exposant biaisé",
      "statement": "Pourquoi l'exposant en IEEE $754$ est-il stocké avec un\n**biais** (par exemple, $+1023$ pour la double précision) ?",
      "options": [
        {
          "text": "Pour simplifier la comparaison entre deux flottants en utilisant la comparaison entière standard",
          "correct": true,
          "feedback": "Bonne réponse : avec un biais, l'exposant est\nstocké comme un entier non signé. Cela permet de\ncomparer deux flottants positifs comme s'ils\nétaient des entiers, ce qui simplifie le matériel\nde comparaison.\n"
        },
        {
          "text": "Pour respecter une convention historique sans intérêt technique",
          "correct": false,
          "feedback": "Erreur : il y a une raison technique précise : la\ncomparaison rapide.\n"
        },
        {
          "text": "Parce que les processeurs ne savent pas gérer les nombres négatifs",
          "correct": false,
          "feedback": "Erreur : les processeurs gèrent très bien les\nnombres signés. Le biais est un choix de design\npour optimiser les comparaisons.\n"
        },
        {
          "text": "Pour économiser de la mémoire",
          "correct": false,
          "feedback": "Erreur : le biais ne change pas la quantité de\nmémoire utilisée (toujours $11$ bits pour\nl'exposant en double précision).\n"
        }
      ],
      "explanation": "Le biais $1023$ pour la double précision est choisi\npour avoir des exposants codés de $0$ à $2046$\n(l'exposant réel va de $-1022$ à $+1023$). Les\nvaleurs $0$ et $2047$ sont réservées aux dénormalisés\net aux infinis/NaN."
    },
    {
      "id": "q22",
      "difficulty": 3,
      "skills": [
        "denormalise"
      ],
      "title": "Nombres dénormalisés",
      "statement": "Quand utilise-t-on des nombres **dénormalisés** en\nIEEE $754$ ?",
      "options": [
        {
          "text": "Pour les très grands nombres",
          "correct": false,
          "feedback": "Erreur : c'est l'inverse. Les très grands nombres\nutilisent l'exposant maximal, pas le minimal.\n"
        },
        {
          "text": "Pour les valeurs spéciales comme NaN",
          "correct": false,
          "feedback": "Erreur : NaN et infinis utilisent une combinaison\nd'exposant maximal et de mantisse particulière, pas\nles dénormalisés.\n"
        },
        {
          "text": "Pour les calculs en simple précision",
          "correct": false,
          "feedback": "Erreur : les dénormalisés existent dans toutes les\nprécisions IEEE $754$.\n"
        },
        {
          "text": "Pour les nombres très proches de zéro, plus petits que le plus petit nombre normalisé représentable",
          "correct": true,
          "feedback": "Bonne réponse : les dénormalisés permettent une\ntransition graduelle vers zéro (au lieu d'un saut\nbrutal). Cela améliore la précision pour les\ncalculs sur de très petites valeurs, au prix d'une\nprécision dégradée.\n"
        }
      ],
      "explanation": "Les dénormalisés peuvent ralentir les processeurs\n(parfois beaucoup), au point que certaines applications\nles désactivent (option « flush to zero »). C'est un\ncompromis subtil entre précision et performance."
    },
    {
      "id": "q23",
      "difficulty": 3,
      "skills": [
        "propagation-erreur"
      ],
      "title": "Propagation des erreurs",
      "statement": "Quel calcul est **numériquement instable** parmi les\nsuivants ?",
      "options": [
        {
          "text": "$a - b$ quand $a$ et $b$ sont très proches (annulation catastrophique)",
          "correct": true,
          "feedback": "Bonne réponse : si $a$ et $b$ sont très proches,\nleur différence a beaucoup moins de chiffres\nsignificatifs que $a$ ou $b$. Les erreurs d'arrondi\ndeviennent dominantes par rapport au résultat.\n"
        },
        {
          "text": "$a + b$ pour $a$ et $b$ de même signe",
          "correct": false,
          "feedback": "Erreur : l'addition de mêmes signes ne pose pas\nde problème de soustraction catastrophique.\n"
        },
        {
          "text": "$a \\times b$ pour $a$ et $b$ proches de $1$",
          "correct": false,
          "feedback": "Erreur : la multiplication n'a pas ce type\nd'instabilité, sauf cas extrêmes (overflow).\n"
        },
        {
          "text": "$a / b$ quand $b$ est grand",
          "correct": false,
          "feedback": "Erreur : ce serait plutôt un problème quand $b$\nest très petit (proche de $0$).\n"
        }
      ],
      "explanation": "Exemple classique : la formule du discriminant pour\nles racines de l'équation du second degré donne des\nrésultats catastrophiques quand le discriminant est\npetit. On utilise alors une forme reformulée\nmathématiquement équivalente mais numériquement\nstable."
    },
    {
      "id": "q24",
      "difficulty": 3,
      "skills": [
        "comparaison-modules"
      ],
      "title": "decimal vs float",
      "statement": "En Python, quelle est la principale différence entre les\nmodules `decimal` et le type `float` ?",
      "options": [
        {
          "text": "`decimal` calcule en base $10$ avec une précision configurable, donc sans erreur d'arrondi pour les nombres décimaux humains",
          "correct": true,
          "feedback": "Bonne réponse : `Decimal('0.1') + Decimal('0.2')`\ndonne exactement `Decimal('0.3')`. C'est essentiel\npour la finance, mais le coût en performance est\nsignificatif (typiquement $10$ à $100$ fois plus\nlent).\n"
        },
        {
          "text": "`decimal` utilise moins de mémoire",
          "correct": false,
          "feedback": "Erreur : c'est plutôt l'inverse. La précision\nconfigurable consomme plus de mémoire.\n"
        },
        {
          "text": "`decimal` est plus rapide",
          "correct": false,
          "feedback": "Erreur : `decimal` est en réalité **plus lent** que\n`float`. Le bénéfice est ailleurs.\n"
        },
        {
          "text": "`decimal` ne fonctionne qu'avec des entiers",
          "correct": false,
          "feedback": "Erreur : `decimal` est précisément destiné aux\nnombres décimaux non entiers.\n"
        }
      ],
      "explanation": "Cette dualité reflète un compromis universel : `float`\noffre la rapidité (calcul en hardware), `decimal`\noffre la précision exacte (calcul logiciel). Le bon\nchoix dépend du contexte applicatif."
    },
    {
      "id": "q25",
      "difficulty": 3,
      "skills": [
        "synthese"
      ],
      "title": "Synthèse sur les flottants",
      "statement": "Parmi les énoncés suivants, lequel est **vrai** sur les\nnombres flottants en machine ?",
      "options": [
        {
          "text": "La précision des flottants augmente avec la taille du nombre",
          "correct": false,
          "feedback": "Erreur : la précision **relative** est constante,\nmais l'erreur **absolue** augmente avec la taille\ndu nombre. Plus un nombre est grand, plus l'écart\nentre deux flottants consécutifs est grand.\n"
        },
        {
          "text": "Les calculs flottants sont aussi précis que les calculs sur papier",
          "correct": false,
          "feedback": "Erreur : on a vu de nombreux contre-exemples\n(associativité, perte de signification, etc.). Les\ncalculs flottants sont approchés.\n"
        },
        {
          "text": "Le test d'égalité `==` entre flottants est souvent piégeur, et il vaut mieux comparer avec une tolérance",
          "correct": true,
          "feedback": "Bonne réponse : c'est l'enseignement le plus\npratique de tout ce chapitre. À cause des erreurs\nd'arrondi, deux flottants qui devraient être égaux\npeuvent légèrement différer. Toujours préférer\n`math.isclose` ou une comparaison à epsilon.\n"
        },
        {
          "text": "Les flottants peuvent représenter exactement tous les nombres rationnels",
          "correct": false,
          "feedback": "Erreur : la plupart des rationnels (par exemple\n$1/3$, $1/10$) n'ont pas de représentation finie\nen binaire. Seul un sous-ensemble fini est\nexactement représenté.\n"
        }
      ],
      "explanation": "Connaître les flottants permet d'éviter des bugs\nsubtils mais critiques dans les calculs scientifiques,\nfinanciers, et même dans des programmes ordinaires\nqui manipulent des nombres réels."
    },
    {
      "id": "q26",
      "difficulty": 2,
      "skills": [
        "conversion",
        "virgule"
      ],
      "title": "Conversion décimal vers binaire avec virgule",
      "statement": "Quelle est l'écriture binaire de $6{,}625$ ?",
      "options": [
        {
          "text": "$1010{,}11$",
          "correct": false,
          "feedback": "Erreur : $1010_2 = 10$, pas $6$. Confusion sur la partie\nentière : $6 = 4 + 2 = 110_2$.\n"
        },
        {
          "text": "$110{,}625$",
          "correct": false,
          "feedback": "Erreur : on a juxtaposé l'écriture décimale de la partie\nfractionnaire à la partie entière en binaire. La partie\ndécimale doit elle aussi être convertie en base $2$.\n"
        },
        {
          "text": "$110{,}11$",
          "correct": false,
          "feedback": "Erreur : la partie décimale $0{,}625$ ne se code pas sur\ndeux bits. On a $0{,}11_2 = 0{,}5 + 0{,}25 = 0{,}75$, ce\nqui ne correspond pas à $0{,}625$.\n"
        },
        {
          "text": "$110{,}101$",
          "correct": true,
          "feedback": "Bonne réponse : la partie entière donne $6 = 110_2$. La\npartie fractionnaire se calcule par multiplications\nsuccessives par $2$ : $0{,}625 \\times 2 = 1{,}25$ (bit\n$1$), puis $0{,}25 \\times 2 = 0{,}5$ (bit $0$), puis\n$0{,}5 \\times 2 = 1{,}0$ (bit $1$). On obtient\n$0{,}101_2$, d'où $110{,}101_2$.\n"
        }
      ],
      "explanation": "Méthode pour la partie fractionnaire : on multiplie par $2$\net on note la partie entière du résultat (bit $0$ ou $1$),\npuis on continue avec la partie fractionnaire restante,\njusqu'à obtenir $0$ ou repérer un cycle. Pour $0{,}625$, on\nobtient $0{,}101_2$ exactement, car $0{,}625 = 0{,}5 + 0{,}125\n= 2^{-1} + 2^{-3}$."
    },
    {
      "id": "q27",
      "difficulty": 2,
      "skills": [
        "base-2",
        "infini"
      ],
      "title": "Décimal sans écriture binaire finie",
      "statement": "Parmi les réels suivants (écrits en base $10$), lequel n'a\n**pas** une écriture finie en base $2$ ?",
      "options": [
        {
          "text": "$0{,}1$",
          "correct": true,
          "feedback": "Bonne réponse : $0{,}1$ ne s'exprime pas comme une somme\nfinie de puissances négatives de $2$. Son écriture\nbinaire est périodique :\n$0{,}0001100110011\\ldots_2$. C'est précisément la cause\nde l'écart entre `0.1 + 0.2` et `0.3` en flottant.\n"
        },
        {
          "text": "$0{,}75$",
          "correct": false,
          "feedback": "Erreur : $0{,}75 = 0{,}5 + 0{,}25 = 2^{-1} + 2^{-2}$,\ndonc son écriture binaire est $0{,}11_2$, finie sur\ndeux bits.\n"
        },
        {
          "text": "$0{,}25$",
          "correct": false,
          "feedback": "Erreur : $0{,}25 = 2^{-2}$, donc son écriture binaire est\n$0{,}01_2$, finie sur deux bits.\n"
        },
        {
          "text": "$0{,}5$",
          "correct": false,
          "feedback": "Erreur : $0{,}5 = 2^{-1}$, donc son écriture binaire est\n$0{,}1_2$, finie sur un seul bit fractionnaire.\n"
        }
      ],
      "explanation": "Un nombre décimal $\\dfrac{p}{q}$ irréductible a une\nécriture binaire finie si et seulement si $q$ est une\npuissance de $2$. Pour $0{,}1 = \\dfrac{1}{10}$,\n$q = 10 = 2 \\times 5$ contient un facteur $5$, ce qui\nprovoque le caractère infini en base $2$. Cette\nobservation explique pourquoi tant de calculs simples en\napparence ($0{,}1 + 0{,}2$) deviennent imprécis sur\nmachine."
    },
    {
      "id": "q28",
      "difficulty": 3,
      "skills": [
        "ieee754",
        "exposant",
        "biais"
      ],
      "title": "Exposant biaisé en simple précision",
      "statement": "Le réel $5{,}5$ s'écrit en notation scientifique binaire\n$5{,}5 = 1{,}011_2 \\times 2^{2}$. Quel est son exposant\n**biaisé** sur huit bits, tel qu'il sera stocké en simple\nprécision (norme IEEE $754$) ?",
      "options": [
        {
          "text": "$2$",
          "correct": false,
          "feedback": "Erreur : $2$ est l'exposant **réel** ($e$), pas l'exposant\nstocké. La norme IEEE $754$ stocke $e + 127$ pour la\nsimple précision afin de représenter tous les exposants\n(positifs et négatifs) sur des bits non signés.\n"
        },
        {
          "text": "$125$",
          "correct": false,
          "feedback": "Erreur : on a soustrait le biais ($2 - 127 = -125$,\nchangement de signe) au lieu de l'ajouter. Pour\n**stocker** l'exposant, on calcule $e + 127$, pas\n$e - 127$.\n"
        },
        {
          "text": "$130$",
          "correct": false,
          "feedback": "Erreur de calcul : $2 + 127 = 129$, pas $130$. Vérifier\nla somme.\n"
        },
        {
          "text": "$129$",
          "correct": true,
          "feedback": "Bonne réponse : en simple précision, le biais est de\n$127$. L'exposant stocké est $e + 127 = 2 + 127 = 129$,\nce qui s'écrit $10000001_2$ sur huit bits.\n"
        }
      ],
      "explanation": "Le biais ($127$ en simple précision, $1023$ en double\nprécision) sert à coder à la fois les exposants positifs et\nnégatifs sur un champ non signé. La formule de décodage est\nsymétrique : valeur lue $E$ → exposant réel\n$e = E - \\text{biais}$. Pour la simple précision, les\nexposants stockés vont de $0$ à $255$, ce qui donne des\nexposants réels de $-127$ à $128$ (avec les valeurs\nextrêmes réservées pour les cas particuliers)."
    },
    {
      "id": "q29",
      "difficulty": 3,
      "skills": [
        "ieee754",
        "decodage"
      ],
      "title": "Décoder un flottant simple précision",
      "statement": "On considère le mot $32$ bits suivant, stocké en simple\nprécision (norme IEEE $754$) :\n\n```\n0 | 10000001 | 01000000000000000000000\n```\n\n(signe sur $1$ bit, exposant sur $8$ bits, mantisse sur\n$23$ bits). Quelle est la valeur décimale représentée ?",
      "options": [
        {
          "text": "$2{,}5$",
          "correct": false,
          "feedback": "Erreur : on a oublié d'ajouter le bit implicite à la\nmantisse. La forme normalisée IEEE $754$ stocke seulement\nles bits **après** la virgule ; la valeur $1$ avant la\nvirgule est implicite. Ici, la mantisse vaut donc\n$1{,}01_2 = 1{,}25$, pas $0{,}25$.\n"
        },
        {
          "text": "$5$",
          "correct": true,
          "feedback": "Bonne réponse : signe `0` (positif), exposant\n$10000001_2 = 129$, donc $e = 129 - 127 = 2$. Mantisse\nimplicite $1{,}01_2 = 1{,}25$. Valeur :\n$1{,}25 \\times 2^2 = 5$.\n"
        },
        {
          "text": "$10$",
          "correct": false,
          "feedback": "Erreur sur l'exposant : on a peut-être lu la mantisse à\nl'envers ou doublé la puissance. L'exposant biaisé vaut\n$129$, donc $e = 2$ et le facteur est $2^2 = 4$, pas\n$2^3 = 8$.\n"
        },
        {
          "text": "$-5$",
          "correct": false,
          "feedback": "Erreur : le bit de signe vaut $0$ (positif). Le résultat\nest $+5$, pas $-5$.\n"
        }
      ],
      "explanation": "Procédure de décodage en trois étapes : (1) lire le bit de\nsigne ; (2) lire l'exposant biaisé $E$ et calculer\n$e = E - 127$ ; (3) reconstituer la mantisse en préfixant le\nbit implicite $1$, puis appliquer la formule\n$(-1)^s \\times 1{,}\\!M \\times 2^e$. Pour cette question :\n$(-1)^0 \\times 1{,}25 \\times 2^2 = 5$."
    }
  ]
}