{
  "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.",
    "parties": [
      {
        "id": "virgule",
        "title": "Virgule fixe et virgule flottante"
      },
      {
        "id": "ieee",
        "title": "Norme IEEE 754"
      },
      {
        "id": "precision",
        "title": "Précision et erreurs d'arrondi"
      },
      {
        "id": "consequences",
        "title": "Comparer des flottants"
      }
    ],
    "prerequisites": [],
    "references": []
  },
  "questions": [
    {
      "id": "q01",
      "difficulty": 1,
      "skills": [
        "definition",
        "type"
      ],
      "title": "Type des réels en Python",
      "partie": "virgule",
      "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 calculs qui\ndoivent rester exacts, comme des montants en centimes, on préfère\ntravailler avec des entiers (`int`)."
    },
    {
      "id": "q02",
      "difficulty": 1,
      "skills": [
        "virgule-flottante"
      ],
      "title": "Notation scientifique",
      "partie": "virgule",
      "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 et un exposant 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",
      "partie": "ieee",
      "statement": "Que définit la norme **IEEE $754$** ?",
      "options": [
        {
          "text": "La représentation binaire des flottants",
          "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. La connectique des câbles réseau relève\nd'autres normes, sans lien avec la représentation des nombres.\n"
        },
        {
          "text": "Le format des adresses IP",
          "correct": false,
          "feedback": "Erreur : le format des adresses IP est fixé par les protocoles\nd'internet. IEEE $754$ concerne les réels.\n"
        },
        {
          "text": "Le format standard des fichiers PDF",
          "correct": false,
          "feedback": "Erreur : le format PDF est défini par sa propre spécification. Il\nn'a aucun lien avec la norme IEEE $754$, qui 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",
      "partie": "precision",
      "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",
      "partie": "precision",
      "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$ (donc sans la moindre erreur)",
          "correct": false,
          "feedback": "Erreur : la valeur exacte stockée est légèrement\n**supérieure** à $0{,}3$, pas inférieure.\n"
        },
        {
          "text": "Proche de $0{,}3$, avec une erreur d'arrondi",
          "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",
      "partie": "consequences",
      "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": "`round(a, 2) == round(b, 2)`",
          "correct": false,
          "feedback": "Erreur : un arrondi ne joue pas le rôle d'une\ntolérance. Deux flottants très proches mais situés de\npart et d'autre d'une frontière d'arrondi (comme\n$1{,}004\\,999$ et $1{,}005\\,001$) sont déclarés\ndifférents, alors que deux valeurs qui s'écartent de\npresque un centième sont déclarées égales.\n"
        },
        {
          "text": "`abs(a - b) < epsilon`",
          "correct": true,
          "feedback": "Bonne réponse : on compare l'écart à une **tolérance**\n`epsilon` choisie petite (par exemple $10^{-9}$), au\nlieu d'exiger une égalité exacte. Le choix\nd'`epsilon` dépend du contexte.\n"
        },
        {
          "text": "`int(a) == int(b)`",
          "correct": false,
          "feedback": "Erreur : `int` supprime la partie décimale, ce qui ne mesure pas\nl'écart : `int(2.1) == int(2.9)` vaut `True` alors que les deux\nflottants diffèrent de $0{,}8$.\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",
      "partie": "virgule",
      "statement": "Quelle est la différence entre une représentation à\n**virgule fixe** et une représentation à **virgule flottante** ?",
      "options": [
        {
          "text": "Fixe = décimales constantes, flottante = 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",
      "partie": "ieee",
      "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": "Avec $64$ bits, on ne peut coder qu'un nombre fini de valeurs : la\nplupart des réels, comme $0{,}1$, ne sont donc stockés que de façon\napprochée."
    },
    {
      "id": "q09",
      "difficulty": 1,
      "skills": [
        "virgule-binaire",
        "conversion"
      ],
      "title": "Écrire un quart en base deux",
      "partie": "virgule",
      "statement": "Quelle est l'écriture en base $2$ du nombre décimal $0{,}25$ ?",
      "options": [
        {
          "text": "$0{,}1_2$",
          "correct": false,
          "feedback": "Erreur : $0{,}1_2$ vaut $2^{-1} = 0{,}5$. Le premier chiffre\naprès la virgule compte les demis, or $0{,}25$ est plus petit\nqu'un demi.\n"
        },
        {
          "text": "$0{,}01_2$",
          "correct": true,
          "feedback": "Bonne réponse : $0{,}25 = \\frac{1}{4} = 2^{-2}$. On a\n$0{,}25 \\times 2 = 0{,}5$ (chiffre $0$), puis $0{,}5 \\times 2 = 1$ (chiffre $1$) : l'écriture s'arrête là.\n"
        },
        {
          "text": "$0{,}11_2$",
          "correct": false,
          "feedback": "Erreur : $0{,}11_2$ vaut $0{,}5 + 0{,}25 = 0{,}75$. Le rang des\ndemis doit rester à $0$, puisque $0{,}25$ est plus petit qu'un demi.\n"
        },
        {
          "text": "$0{,}25_2$",
          "correct": false,
          "feedback": "Erreur : en base $2$, seuls les chiffres $0$ et $1$ existent. On\nne recopie pas l'écriture décimale après la virgule.\n"
        }
      ],
      "explanation": "Après la virgule, les rangs en base $2$ valent $\\frac{1}{2}$,\n$\\frac{1}{4}$, $\\frac{1}{8}$, etc. Comme $0{,}25 = \\frac{1}{4} = 2^{-2}$,\nson écriture binaire est finie et courte : $0{,}01_2$. Ce nombre\nest donc stocké exactement dans un flottant, contrairement à\n$0{,}1$.",
      "variants": [
        {
          "statement": "Quelle est l'écriture en base $2$ du nombre décimal $0{,}25$ ?",
          "options": [
            {
              "text": "$0{,}1_2$",
              "correct": false,
              "feedback": "Erreur : $0{,}1_2$ vaut $2^{-1} = 0{,}5$. Le premier chiffre\naprès la virgule compte les demis, or $0{,}25$ est plus petit\nqu'un demi.\n"
            },
            {
              "text": "$0{,}01_2$",
              "correct": true,
              "feedback": "Bonne réponse : $0{,}25 = \\frac{1}{4} = 2^{-2}$. On a\n$0{,}25 \\times 2 = 0{,}5$ (chiffre $0$), puis $0{,}5 \\times 2 = 1$ (chiffre $1$) : l'écriture s'arrête là.\n"
            },
            {
              "text": "$0{,}11_2$",
              "correct": false,
              "feedback": "Erreur : $0{,}11_2$ vaut $0{,}5 + 0{,}25 = 0{,}75$. Le rang des\ndemis doit rester à $0$, puisque $0{,}25$ est plus petit qu'un demi.\n"
            },
            {
              "text": "$0{,}25_2$",
              "correct": false,
              "feedback": "Erreur : en base $2$, seuls les chiffres $0$ et $1$ existent. On\nne recopie pas l'écriture décimale après la virgule.\n"
            }
          ],
          "explanation": "Après la virgule, les rangs en base $2$ valent $\\frac{1}{2}$,\n$\\frac{1}{4}$, $\\frac{1}{8}$, etc. Comme $0{,}25 = \\frac{1}{4} = 2^{-2}$,\nson écriture binaire est finie et courte : $0{,}01_2$. Ce nombre\nest donc stocké exactement dans un flottant, contrairement à\n$0{,}1$."
        },
        {
          "statement": "Quelle est l'écriture en base $2$ du nombre décimal $0{,}125$ ?",
          "options": [
            {
              "text": "$0{,}1_2$",
              "correct": false,
              "feedback": "Erreur : $0{,}1_2$ vaut $2^{-1} = 0{,}5$. Le premier chiffre\naprès la virgule compte les demis, or $0{,}125$ est plus petit\nqu'un demi.\n"
            },
            {
              "text": "$0{,}001_2$",
              "correct": true,
              "feedback": "Bonne réponse : $0{,}125 = \\frac{1}{8} = 2^{-3}$. On a\n$0{,}125 \\times 2 = 0{,}25$ (chiffre $0$), puis $0{,}25 \\times 2 = 0{,}5$ (chiffre $0$), puis $0{,}5 \\times 2 = 1$ (chiffre $1$) : l'écriture s'arrête là.\n"
            },
            {
              "text": "$0{,}11_2$",
              "correct": false,
              "feedback": "Erreur : $0{,}11_2$ vaut $0{,}5 + 0{,}25 = 0{,}75$. Le rang des\ndemis doit rester à $0$, puisque $0{,}125$ est plus petit qu'un demi.\n"
            },
            {
              "text": "$0{,}125_2$",
              "correct": false,
              "feedback": "Erreur : en base $2$, seuls les chiffres $0$ et $1$ existent. On\nne recopie pas l'écriture décimale après la virgule.\n"
            }
          ],
          "explanation": "Après la virgule, les rangs en base $2$ valent $\\frac{1}{2}$,\n$\\frac{1}{4}$, $\\frac{1}{8}$, etc. Comme $0{,}125 = \\frac{1}{8} = 2^{-3}$,\nson écriture binaire est finie et courte : $0{,}001_2$. Ce nombre\nest donc stocké exactement dans un flottant, contrairement à\n$0{,}1$."
        },
        {
          "statement": "Quelle est l'écriture en base $2$ du nombre décimal $0{,}375$ ?",
          "options": [
            {
              "text": "$0{,}1_2$",
              "correct": false,
              "feedback": "Erreur : $0{,}1_2$ vaut $2^{-1} = 0{,}5$. Le premier chiffre\naprès la virgule compte les demis, or $0{,}375$ est plus petit\nqu'un demi.\n"
            },
            {
              "text": "$0{,}011_2$",
              "correct": true,
              "feedback": "Bonne réponse : $0{,}375 = \\frac{3}{8} = \\frac{1}{4} + \\frac{1}{8}$. On a\n$0{,}375 \\times 2 = 0{,}75$ (chiffre $0$), puis $0{,}75 \\times 2 = 1{,}5$ (chiffre $1$), puis $0{,}5 \\times 2 = 1$ (chiffre $1$) : l'écriture s'arrête là.\n"
            },
            {
              "text": "$0{,}11_2$",
              "correct": false,
              "feedback": "Erreur : $0{,}11_2$ vaut $0{,}5 + 0{,}25 = 0{,}75$. Le rang des\ndemis doit rester à $0$, puisque $0{,}375$ est plus petit qu'un demi.\n"
            },
            {
              "text": "$0{,}375_2$",
              "correct": false,
              "feedback": "Erreur : en base $2$, seuls les chiffres $0$ et $1$ existent. On\nne recopie pas l'écriture décimale après la virgule.\n"
            }
          ],
          "explanation": "Après la virgule, les rangs en base $2$ valent $\\frac{1}{2}$,\n$\\frac{1}{4}$, $\\frac{1}{8}$, etc. Comme $0{,}375 = \\frac{3}{8} = \\frac{1}{4} + \\frac{1}{8}$,\nson écriture binaire est finie et courte : $0{,}011_2$. Ce nombre\nest donc stocké exactement dans un flottant, contrairement à\n$0{,}1$."
        }
      ]
    },
    {
      "id": "q10",
      "difficulty": 2,
      "skills": [
        "comparaison-flottants",
        "ecriture-binaire",
        "assertion"
      ],
      "title": "Deux assertions sur des moyennes",
      "partie": "consequences",
      "statement": "Pour tester une fonction `moyenne`, on exécute le\nprogramme suivant :\n\n```python\ndef moyenne(a, b):\n    return (a + b) / 2\n\nassert moyenne(0.25, 0.75) == 0.5\nassert moyenne(0.1, 0.2) == 0.15\n```\n\nQue se passe-t-il ?",
      "options": [
        {
          "text": "Les deux assertions sont vérifiées, le programme se termine sans erreur",
          "correct": false,
          "feedback": "Erreur : $0{,}1$ et $0{,}2$ n'ont pas d'écriture\nbinaire finie, ils sont stockés arrondis. Leur\nmoyenne vaut `0.15000000000000002`, et l'égalité\navec `0.15` est fausse.\n"
        },
        {
          "text": "La première assertion est vérifiée, la seconde lève `AssertionError`",
          "correct": true,
          "feedback": "Bonne réponse : $0{,}25 = 0{,}01_2$ et\n$0{,}75 = 0{,}11_2$ s'écrivent exactement en\nbinaire, donc la première moyenne vaut\nexactement $0{,}5$. En revanche, $0{,}1$ et $0{,}2$\nsont arrondis : leur moyenne vaut\n`0.15000000000000002`, et la seconde égalité est\nfausse.\n"
        },
        {
          "text": "La première assertion lève `AssertionError` et arrête le programme",
          "correct": false,
          "feedback": "Erreur : $0{,}25$, $0{,}75$ et $0{,}5$ sont des sommes\nde puissances de $2$ ($0{,}01_2$, $0{,}11_2$ et\n$0{,}1_2$) : ils sont représentés exactement, et\nla première égalité est vraie.\n"
        },
        {
          "text": "Python refuse d'évaluer `==` entre deux flottants et lève une erreur",
          "correct": false,
          "feedback": "Erreur : `==` s'applique aux flottants comme aux\nentiers. Il est seulement déconseillé, car deux\ncalculs censés donner la même valeur peuvent\ndifférer à cause des arrondis.\n"
        }
      ],
      "explanation": "Un nombre a une écriture binaire finie seulement\ns'il est une somme d'un nombre fini de puissances\nde $2$, comme $0{,}75 = 2^{-1} + 2^{-2}$. Ce n'est\npas le cas de $0{,}1 = 0{,}0001100110011\\ldots_2$,\nqui est arrondi. Pour tester un résultat flottant,\non compare l'écart à une tolérance :\n`assert abs(moyenne(0.1, 0.2) - 0.15) < 1e-9`."
    },
    {
      "id": "q11",
      "difficulty": 2,
      "skills": [
        "calcul",
        "erreur"
      ],
      "title": "Erreur d'arrondi cumulative",
      "partie": "precision",
      "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 s'accumulent et faussent le résultat",
          "correct": true,
          "feedback": "Bonne réponse : c'est un piège classique en calcul scientifique.\nChaque addition arrondit un peu, et sur des millions d'opérations\nces écarts s'additionnent. Quand c'est possible, on travaille avec\ndes entiers, qui restent exacts.\n"
        }
      ],
      "explanation": "Un exemple frappant : additionner dix fois `0.1` dans une boucle\n`for` donne `0.9999999999999999`, pas $1{,}0$, à cause des erreurs\ncumulées. Pour des montants, on compte en centimes avec des\nentiers."
    },
    {
      "id": "q12",
      "difficulty": 2,
      "skills": [
        "comparaison-flottants",
        "python"
      ],
      "title": "Un prix calculé qui échappe au test",
      "partie": "consequences",
      "statement": "Un programme compte les articles vendus $0{,}30$ euro :\n\n```python\nprix = [0.1 + 0.2, 0.5, 0.3]\ncompte = 0\nfor p in prix:\n    if p == 0.3:\n        compte = compte + 1\nprint(compte)\n```\n\nQu'affiche ce programme ?",
      "options": [
        {
          "text": "`2`",
          "correct": false,
          "feedback": "Erreur : `0.1 + 0.2` ne vaut pas `0.3` en Python mais\n`0.30000000000000004`. Le test `p == 0.3` est donc faux pour le\npremier prix, et seul le dernier est compté.\n"
        },
        {
          "text": "`1`",
          "correct": true,
          "feedback": "Bonne réponse : seul le dernier prix, écrit directement `0.3`,\npasse le test. Le premier, calculé, vaut `0.30000000000000004` et\néchoue à l'égalité stricte.\n"
        },
        {
          "text": "`0`",
          "correct": false,
          "feedback": "Erreur : l'égalité entre flottants n'est pas toujours fausse. Le\ndernier élément de la liste et le littéral `0.3` du test sont\nexactement le même flottant, le test réussit pour ce prix.\n"
        },
        {
          "text": "Une erreur, car `==` ne compare pas des flottants",
          "correct": false,
          "feedback": "Erreur : `==` s'applique aux flottants et renvoie un booléen. Le\nprogramme s'exécute sans erreur ; c'est le résultat du test qui\nsurprend.\n"
        }
      ],
      "explanation": "Le programme illustre la règle : il faut éviter de tester l'égalité\nde deux flottants. Avec la condition `abs(p - 0.3) < 1e-9`, les\ndeux prix de $0{,}30$ euro seraient comptés."
    },
    {
      "id": "q13",
      "difficulty": 2,
      "skills": [
        "virgule-binaire",
        "conversion"
      ],
      "title": "Valeur décimale d'une écriture binaire à virgule",
      "partie": "virgule",
      "statement": "Quelle est la valeur décimale du nombre écrit en base $2$ :\n$110{,}01_2$ ?",
      "options": [
        {
          "text": "$6{,}01$",
          "correct": false,
          "feedback": "Erreur : la partie entière $110_2 = 6$ est juste, mais les\nchiffres après la virgule ne se recopient pas : $0{,}01_2$ vaut\n$0{,}25$.\n"
        },
        {
          "text": "$6{,}5$",
          "correct": false,
          "feedback": "Erreur : $0{,}01_2$ n'est pas un demi. Chaque rang après la\nvirgule a son poids, $\\frac{1}{2}$, $\\frac{1}{4}$, $\\frac{1}{8}$,\nd'où $0{,}25$.\n"
        },
        {
          "text": "$6{,}25$",
          "correct": true,
          "feedback": "Bonne réponse : $110_2 = 4 + 2 = 6$ et\n$0{,}01_2 = 0 \\times \\frac{1}{2} + 1 \\times \\frac{1}{4} = 0{,}25$,\nsoit $6{,}25$.\n"
        },
        {
          "text": "$3{,}25$",
          "correct": false,
          "feedback": "Erreur : on a lu la partie entière à l'envers, comme\n$011_2 = 3$. Le chiffre de gauche a le poids le plus fort :\n$110_2 = 4 + 2 = 6$.\n"
        }
      ],
      "explanation": "Chaque rang a un poids : des puissances de $2$ avant la virgule, puis\n$\\frac{1}{2}$, $\\frac{1}{4}$, $\\frac{1}{8}$ après. On additionne\nles poids des chiffres $1$ : $4 + 2 + \\frac{1}{4} = 6{,}25$.",
      "variants": [
        {
          "statement": "Quelle est la valeur décimale du nombre écrit en base $2$ :\n$110{,}01_2$ ?",
          "options": [
            {
              "text": "$6{,}01$",
              "correct": false,
              "feedback": "Erreur : la partie entière $110_2 = 6$ est juste, mais les\nchiffres après la virgule ne se recopient pas : $0{,}01_2$ vaut\n$0{,}25$.\n"
            },
            {
              "text": "$6{,}5$",
              "correct": false,
              "feedback": "Erreur : $0{,}01_2$ n'est pas un demi. Chaque rang après la\nvirgule a son poids, $\\frac{1}{2}$, $\\frac{1}{4}$, $\\frac{1}{8}$,\nd'où $0{,}25$.\n"
            },
            {
              "text": "$6{,}25$",
              "correct": true,
              "feedback": "Bonne réponse : $110_2 = 4 + 2 = 6$ et\n$0{,}01_2 = 0 \\times \\frac{1}{2} + 1 \\times \\frac{1}{4} = 0{,}25$,\nsoit $6{,}25$.\n"
            },
            {
              "text": "$3{,}25$",
              "correct": false,
              "feedback": "Erreur : on a lu la partie entière à l'envers, comme\n$011_2 = 3$. Le chiffre de gauche a le poids le plus fort :\n$110_2 = 4 + 2 = 6$.\n"
            }
          ],
          "explanation": "Chaque rang a un poids : des puissances de $2$ avant la virgule, puis\n$\\frac{1}{2}$, $\\frac{1}{4}$, $\\frac{1}{8}$ après. On additionne\nles poids des chiffres $1$ : $4 + 2 + \\frac{1}{4} = 6{,}25$."
        },
        {
          "statement": "Quelle est la valeur décimale du nombre écrit en base $2$ :\n$100{,}11_2$ ?",
          "options": [
            {
              "text": "$4{,}11$",
              "correct": false,
              "feedback": "Erreur : la partie entière $100_2 = 4$ est juste, mais les\nchiffres après la virgule ne se recopient pas : $0{,}11_2$ vaut\n$0{,}75$.\n"
            },
            {
              "text": "$4{,}5$",
              "correct": false,
              "feedback": "Erreur : $0{,}11_2$ n'est pas un demi. Chaque rang après la\nvirgule a son poids, $\\frac{1}{2}$, $\\frac{1}{4}$, $\\frac{1}{8}$,\nd'où $0{,}75$.\n"
            },
            {
              "text": "$4{,}75$",
              "correct": true,
              "feedback": "Bonne réponse : $100_2 = 4 = 4$ et\n$0{,}11_2 = 1 \\times \\frac{1}{2} + 1 \\times \\frac{1}{4} = 0{,}75$,\nsoit $4{,}75$.\n"
            },
            {
              "text": "$1{,}75$",
              "correct": false,
              "feedback": "Erreur : on a lu la partie entière à l'envers, comme\n$001_2 = 1$. Le chiffre de gauche a le poids le plus fort :\n$100_2 = 4 = 4$.\n"
            }
          ],
          "explanation": "Chaque rang a un poids : des puissances de $2$ avant la virgule, puis\n$\\frac{1}{2}$, $\\frac{1}{4}$, $\\frac{1}{8}$ après. On additionne\nles poids des chiffres $1$ : $4 + \\frac{1}{2} + \\frac{1}{4} = 4{,}75$."
        },
        {
          "statement": "Quelle est la valeur décimale du nombre écrit en base $2$ :\n$1011{,}001_2$ ?",
          "options": [
            {
              "text": "$11{,}001$",
              "correct": false,
              "feedback": "Erreur : la partie entière $1011_2 = 11$ est juste, mais les\nchiffres après la virgule ne se recopient pas : $0{,}001_2$ vaut\n$0{,}125$.\n"
            },
            {
              "text": "$11{,}5$",
              "correct": false,
              "feedback": "Erreur : $0{,}001_2$ n'est pas un demi. Chaque rang après la\nvirgule a son poids, $\\frac{1}{2}$, $\\frac{1}{4}$, $\\frac{1}{8}$,\nd'où $0{,}125$.\n"
            },
            {
              "text": "$11{,}125$",
              "correct": true,
              "feedback": "Bonne réponse : $1011_2 = 8 + 2 + 1 = 11$ et\n$0{,}001_2 = 0 \\times \\frac{1}{2} + 0 \\times \\frac{1}{4} + 1 \\times \\frac{1}{8} = 0{,}125$,\nsoit $11{,}125$.\n"
            },
            {
              "text": "$13{,}125$",
              "correct": false,
              "feedback": "Erreur : on a lu la partie entière à l'envers, comme\n$1101_2 = 13$. Le chiffre de gauche a le poids le plus fort :\n$1011_2 = 8 + 2 + 1 = 11$.\n"
            }
          ],
          "explanation": "Chaque rang a un poids : des puissances de $2$ avant la virgule, puis\n$\\frac{1}{2}$, $\\frac{1}{4}$, $\\frac{1}{8}$ après. On additionne\nles poids des chiffres $1$ : $8 + 2 + 1 + \\frac{1}{8} = 11{,}125$."
        }
      ]
    },
    {
      "id": "q15",
      "difficulty": 2,
      "skills": [
        "calcul-financier"
      ],
      "title": "Calcul financier",
      "partie": "precision",
      "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 en Python",
          "correct": false,
          "feedback": "Erreur : aucun rapport avec les nombres complexes.\n"
        },
        {
          "text": "Stocker les montants en centimes entiers",
          "correct": true,
          "feedback": "Bonne réponse : les entiers sont exacts en Python. On compte en\ncentimes et on ne convertit en euros qu'au moment de l'affichage.\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 erreurs d'arrondi des `float` sont inacceptables pour des\nmontants : la précision doit être garantie au centime. Compter en\ncentimes avec des entiers supprime le problème."
    },
    {
      "id": "q16",
      "difficulty": 2,
      "skills": [
        "conversion",
        "float"
      ],
      "title": "Conversion entier vers flottant",
      "partie": "virgule",
      "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$.",
      "variants": [
        {
          "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$."
        },
        {
          "statement": "En Python, l'instruction `float(3)` renvoie :",
          "options": [
            {
              "text": "`3` (entier inchangé)",
              "correct": false,
              "feedback": "Erreur : la fonction `float` change le type. Le\nrésultat est `3.0`, qui est un flottant.\n"
            },
            {
              "text": "`3.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": "`'3'` (chaîne de caractères)",
              "correct": false,
              "feedback": "Erreur : `float()` convertit en flottant, pas en\nchaîne. Pour une chaîne, on utiliserait `str(3)`.\n"
            }
          ],
          "explanation": "Inversement, `int(7.9)` renvoie $7$ (troncature, pas\narrondi). Pour arrondir, on utilise `round(7.9)` qui\nrenvoie $8$."
        },
        {
          "statement": "En Python, l'instruction `float(12)` renvoie :",
          "options": [
            {
              "text": "`12` (entier inchangé)",
              "correct": false,
              "feedback": "Erreur : la fonction `float` change le type. Le\nrésultat est `12.0`, qui est un flottant.\n"
            },
            {
              "text": "`12.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": "`'12'` (chaîne de caractères)",
              "correct": false,
              "feedback": "Erreur : `float()` convertit en flottant, pas en\nchaîne. Pour une chaîne, on utiliserait `str(12)`.\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",
      "partie": "precision",
      "statement": "Pourquoi `(1e16 + 1) - 1e16` donne-t-il $0$ en Python\nau lieu de $1$ ?",
      "options": [
        {
          "text": "$1$ est négligeable face à $10^{16}$ pour la mantisse",
          "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",
      "partie": "ieee",
      "statement": "En base $2$, la notation scientifique **normalisée** d'un réel non\nnul a la forme :",
      "options": [
        {
          "text": "$0{,}m \\times 2^e$ avec $m$ quelconque",
          "correct": false,
          "feedback": "Erreur : la forme normalisée place un seul chiffre, qui vaut $1$,\navant la virgule : sa mantisse est comprise entre $1$ et $2$, pas\nentre $0$ et $1$.\n"
        },
        {
          "text": "$1{,}m \\times 2^e$",
          "correct": true,
          "feedback": "Bonne réponse : en binaire, le premier chiffre non nul d'un nombre\nest toujours $1$. On place la virgule juste après ce $1$ et on\ncompense par la puissance de $2$ : par exemple\n$6 = 110_2 = 1{,}1_2 \\times 2^{2}$.\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": "C'est l'analogue de la notation scientifique décimale, où l'on écrit\n$350 = 3{,}5 \\times 10^{2}$ avec un seul chiffre non nul avant la\nvirgule. En base $2$, ce chiffre ne peut être que $1$."
    },
    {
      "id": "q19",
      "difficulty": 2,
      "skills": [
        "associativite"
      ],
      "title": "Non-associativité de l'addition flottante",
      "partie": "precision",
      "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 change le résultat",
          "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, exactement 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",
      "partie": "virgule",
      "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": "$0{,}5 = 2^{-1}$ est une puissance de $2$, pas $0{,}1$",
          "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$. Toute base\nprivilégie certaines fractions et en désavantage d'autres. Pour des\nmontants, compter en centimes avec des entiers évite ce problème."
    },
    {
      "id": "q23",
      "difficulty": 3,
      "skills": [
        "propagation-erreur"
      ],
      "title": "Propagation des erreurs",
      "partie": "precision",
      "statement": "Avec des flottants, quel calcul fait perdre le plus de chiffres\nsignificatifs exacts parmi les suivants ?",
      "options": [
        {
          "text": "$a - b$ avec $a$ et $b$ très proches",
          "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 : ajouter deux nombres de même signe conserve les premiers\nchiffres du résultat ; les erreurs d'arrondi restent petites\ndevant lui.\n"
        },
        {
          "text": "$a \\times b$ pour $a$ et $b$ proches de $1$",
          "correct": false,
          "feedback": "Erreur : multiplier deux nombres proches de $1$ donne un résultat\nproche de $1$, dont les erreurs d'arrondi restent du même ordre que\ncelles des facteurs.\n"
        },
        {
          "text": "$a / b$ quand $b$ est grand",
          "correct": false,
          "feedback": "Erreur : diviser par un grand nombre donne un petit résultat, mais\nses chiffres significatifs restent aussi exacts que ceux de $a$ et\n$b$.\n"
        }
      ],
      "explanation": "Exemple : en Python, `1.0000001 - 1.0` affiche\n`1.0000000005838672e-07` au lieu de `1e-07`. Les chiffres de tête\ncommuns s'annulent, et il ne reste que des chiffres dont une partie\nprovient des erreurs d'arrondi."
    },
    {
      "id": "q24",
      "difficulty": 3,
      "skills": [
        "comparaison-flottants",
        "tolerance"
      ],
      "title": "Une tolérance mal dimensionnée",
      "partie": "consequences",
      "statement": "Sarah compare deux flottants avec une tolérance fixe :\n```python\ndef proches(a, b):\n    return abs(a - b) < 1e-9\n\nprint(proches(1e-12, 2e-12))\n```\nLe programme affiche `True`, alors que `2e-12` est le\ndouble de `1e-12`. Comment expliquer ce résultat ?",
      "options": [
        {
          "text": "La tolérance $10^{-9}$ est énorme devant les valeurs comparées, il faut l'adapter à leur ordre de grandeur",
          "correct": true,
          "feedback": "Bonne réponse : l'écart réel vaut $10^{-12}$, mille fois\nplus petit que la tolérance, donc le test réussit quelle\nque soit la différence entre `a` et `b`. Une tolérance\nfixe n'a de sens que pour des valeurs d'ordre de grandeur\nconnu ; sinon, on la rend relative, par exemple\n`abs(a - b) < 1e-9 * abs(b)`, qui renvoie ici `False`.\n"
        },
        {
          "text": "Les deux valeurs sont plus petites que le plus petit flottant représentable et valent donc toutes deux `0.0` en machine",
          "correct": false,
          "feedback": "Erreur : un flottant $64$ bits descend jusqu'à environ\n$10^{-308}$, bien en dessous de $10^{-12}$. Les deux\nvaleurs sont représentées et distinctes : `1e-12 == 2e-12`\nrenvoie `False`.\n"
        },
        {
          "text": "La soustraction de deux flottants aussi proches subit une annulation et renvoie exactement `0.0`, d'où un écart nul",
          "correct": false,
          "feedback": "Erreur : `1e-12 - 2e-12` renvoie `-1e-12`, un écart non\nnul. L'annulation qui menace une soustraction concerne\ndes valeurs presque égales, pas des valeurs du simple au\ndouble.\n"
        },
        {
          "text": "Le test est correct, car deux flottants qui diffèrent de moins de $10^{-9}$ sont indiscernables pour la machine",
          "correct": false,
          "feedback": "Erreur : la machine distingue parfaitement `1e-12` et\n`2e-12` ; l'indiscernabilité ne concerne que des écarts\nrelatifs de l'ordre de $10^{-16}$. C'est le seuil choisi\npar Sarah qui est inadapté, pas la représentation.\n"
        }
      ],
      "explanation": "Une tolérance absolue ne vaut que pour un ordre de grandeur\ndonné : $10^{-9}$ convient pour des valeurs proches de $1$,\nmais tout écart entre des valeurs de l'ordre de $10^{-12}$\nlui est inférieur. Quand l'ordre de grandeur n'est pas connu\nd'avance, on compare l'écart à une fraction des valeurs\nelles-mêmes (tolérance relative)."
    },
    {
      "id": "q25",
      "difficulty": 3,
      "skills": [
        "synthese"
      ],
      "title": "Synthèse sur les flottants",
      "partie": "consequences",
      "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 `==` entre flottants est piégeux, préférer 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 une\ncomparaison à une tolérance, du type\n`abs(a - b) < 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": [
        "virgule-binaire",
        "conversion"
      ],
      "title": "Conversion décimal vers binaire avec virgule",
      "partie": "virgule",
      "statement": "Quelle est l'écriture binaire de $6{,}625$ ?",
      "options": [
        {
          "text": "$1010{,}101$",
          "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{,}100$",
          "correct": false,
          "feedback": "Erreur : $0{,}100_2$ vaut $0{,}5$, ce qui ne correspond pas\nà $0{,}625$. Il faut poursuivre les multiplications par $2$\njusqu'à épuiser la partie fractionnaire.\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 $1$), puis $0{,}25 \\times 2 = 0{,}5$ (bit $0$), puis $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 = 2^{-1} + 2^{-3}$.",
      "variants": [
        {
          "statement": "Quelle est l'écriture binaire de $6{,}625$ ?",
          "options": [
            {
              "text": "$1010{,}101$",
              "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{,}100$",
              "correct": false,
              "feedback": "Erreur : $0{,}100_2$ vaut $0{,}5$, ce qui ne correspond pas\nà $0{,}625$. Il faut poursuivre les multiplications par $2$\njusqu'à épuiser la partie fractionnaire.\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 $1$), puis $0{,}25 \\times 2 = 0{,}5$ (bit $0$), puis $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 = 2^{-1} + 2^{-3}$."
        },
        {
          "statement": "Quelle est l'écriture binaire de $5{,}75$ ?",
          "options": [
            {
              "text": "$1001{,}11$",
              "correct": false,
              "feedback": "Erreur : $1001_2 = 9$, pas $5$. Confusion sur la partie\nentière : $5 = 4 + 1 = 101_2$.\n"
            },
            {
              "text": "$101{,}75$",
              "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": "$101{,}10$",
              "correct": false,
              "feedback": "Erreur : $0{,}10_2$ vaut $0{,}5$, ce qui ne correspond pas\nà $0{,}75$. Il faut poursuivre les multiplications par $2$\njusqu'à épuiser la partie fractionnaire.\n"
            },
            {
              "text": "$101{,}11$",
              "correct": true,
              "feedback": "Bonne réponse : la partie entière donne $5 = 101_2$. La\npartie fractionnaire se calcule par multiplications\nsuccessives par $2$ : $0{,}75 \\times 2 = 1{,}5$ (bit $1$), puis $0{,}5 \\times 2 = 1{,}0$ (bit $1$). On obtient\n$0{,}11_2$, d'où $101{,}11_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{,}75$, on\nobtient $0{,}11_2$ exactement, car $0{,}75 = 0{,}5 + 0{,}25 = 2^{-1} + 2^{-2}$."
        },
        {
          "statement": "Quelle est l'écriture binaire de $9{,}375$ ?",
          "options": [
            {
              "text": "$1101{,}011$",
              "correct": false,
              "feedback": "Erreur : $1101_2 = 13$, pas $9$. Confusion sur la partie\nentière : $9 = 8 + 1 = 1001_2$.\n"
            },
            {
              "text": "$1001{,}375$",
              "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": "$1001{,}100$",
              "correct": false,
              "feedback": "Erreur : $0{,}100_2$ vaut $0{,}5$, ce qui ne correspond pas\nà $0{,}375$. Il faut poursuivre les multiplications par $2$\njusqu'à épuiser la partie fractionnaire.\n"
            },
            {
              "text": "$1001{,}011$",
              "correct": true,
              "feedback": "Bonne réponse : la partie entière donne $9 = 1001_2$. La\npartie fractionnaire se calcule par multiplications\nsuccessives par $2$ : $0{,}375 \\times 2 = 0{,}75$ (bit $0$), puis $0{,}75 \\times 2 = 1{,}5$ (bit $1$), puis $0{,}5 \\times 2 = 1{,}0$ (bit $1$). On obtient\n$0{,}011_2$, d'où $1001{,}011_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{,}375$, on\nobtient $0{,}011_2$ exactement, car $0{,}375 = 0{,}25 + 0{,}125 = 2^{-2} + 2^{-3}$."
        }
      ]
    },
    {
      "id": "q27",
      "difficulty": 2,
      "skills": [
        "base-2",
        "infini"
      ],
      "title": "Décimal sans écriture binaire finie",
      "partie": "virgule",
      "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": 2,
      "skills": [
        "ieee",
        "exposant"
      ],
      "title": "Exposant biaisé en simple précision",
      "partie": "ieee",
      "statement": "Le réel $5{,}5$ s'écrit en notation scientifique binaire\n$5{,}5 = 1{,}011_2 \\times 2^{2}$. Dans le format simple précision,\nl'exposant n'est pas stocké tel quel : on lui ajoute $127$ avant de\nl'écrire sur huit bits. Quelle suite de huit bits est stockée dans\nce champ ?",
      "options": [
        {
          "text": "$00000010_2$",
          "correct": false,
          "feedback": "Erreur : $00000010_2 = 2$ est l'exposant **réel**, écrit sans lui\najouter $127$ comme le demande le format.\n"
        },
        {
          "text": "$01111101_2$",
          "correct": false,
          "feedback": "Erreur : $01111101_2 = 125$ ; on a soustrait $127$ au lieu de\nl'ajouter ($2 - 127 = -125$, puis on a oublié le signe). Le champ\ncontient $2 + 127 = 129$.\n"
        },
        {
          "text": "$10000010_2$",
          "correct": false,
          "feedback": "Erreur : $10000010_2 = 130$, soit $2 + 128$. Le décalage du format\nvaut $127$ et non $128$ : le champ contient $129$.\n"
        },
        {
          "text": "$10000001_2$",
          "correct": true,
          "feedback": "Bonne réponse : l'exposant stocké est $2 + 127 = 129 = 128 + 1$, ce\nqui s'écrit $10000001_2$ sur huit bits.\n"
        }
      ],
      "explanation": "Ajouter $127$ permet de ranger aussi les exposants négatifs dans un\nchamp de huit bits sans signe : un exposant réel $-1$ est stocké\n$126$. Pour relire l'exposant, on retire $127$ à la valeur stockée.",
      "variants": [
        {
          "statement": "Le réel $5{,}5$ s'écrit en notation scientifique binaire\n$5{,}5 = 1{,}011_2 \\times 2^{2}$. Dans le format simple précision,\nl'exposant n'est pas stocké tel quel : on lui ajoute $127$ avant de\nl'écrire sur huit bits. Quelle suite de huit bits est stockée dans\nce champ ?",
          "options": [
            {
              "text": "$00000010_2$",
              "correct": false,
              "feedback": "Erreur : $00000010_2 = 2$ est l'exposant **réel**, écrit sans lui\najouter $127$ comme le demande le format.\n"
            },
            {
              "text": "$01111101_2$",
              "correct": false,
              "feedback": "Erreur : $01111101_2 = 125$ ; on a soustrait $127$ au lieu de\nl'ajouter ($2 - 127 = -125$, puis on a oublié le signe). Le champ\ncontient $2 + 127 = 129$.\n"
            },
            {
              "text": "$10000010_2$",
              "correct": false,
              "feedback": "Erreur : $10000010_2 = 130$, soit $2 + 128$. Le décalage du format\nvaut $127$ et non $128$ : le champ contient $129$.\n"
            },
            {
              "text": "$10000001_2$",
              "correct": true,
              "feedback": "Bonne réponse : l'exposant stocké est $2 + 127 = 129 = 128 + 1$, ce\nqui s'écrit $10000001_2$ sur huit bits.\n"
            }
          ],
          "explanation": "Ajouter $127$ permet de ranger aussi les exposants négatifs dans un\nchamp de huit bits sans signe : un exposant réel $-1$ est stocké\n$126$. Pour relire l'exposant, on retire $127$ à la valeur stockée."
        },
        {
          "statement": "Le réel $12$ s'écrit en notation scientifique binaire\n$12 = 1{,}1_2 \\times 2^{3}$. Dans le format simple précision,\nl'exposant n'est pas stocké tel quel : on lui ajoute $127$ avant de\nl'écrire sur huit bits. Quelle suite de huit bits est stockée dans\nce champ ?",
          "options": [
            {
              "text": "$00000011_2$",
              "correct": false,
              "feedback": "Erreur : $00000011_2 = 3$ est l'exposant **réel**, écrit sans lui\najouter $127$ comme le demande le format.\n"
            },
            {
              "text": "$01111100_2$",
              "correct": false,
              "feedback": "Erreur : $01111100_2 = 124$ ; on a soustrait $127$ au lieu de\nl'ajouter ($3 - 127 = -124$, puis on a oublié le signe). Le champ\ncontient $3 + 127 = 130$.\n"
            },
            {
              "text": "$10000011_2$",
              "correct": false,
              "feedback": "Erreur : $10000011_2 = 131$, soit $3 + 128$. Le décalage du format\nvaut $127$ et non $128$ : le champ contient $130$.\n"
            },
            {
              "text": "$10000010_2$",
              "correct": true,
              "feedback": "Bonne réponse : l'exposant stocké est $3 + 127 = 130 = 128 + 2$, ce\nqui s'écrit $10000010_2$ sur huit bits.\n"
            }
          ],
          "explanation": "Ajouter $127$ permet de ranger aussi les exposants négatifs dans un\nchamp de huit bits sans signe : un exposant réel $-1$ est stocké\n$126$. Pour relire l'exposant, on retire $127$ à la valeur stockée."
        },
        {
          "statement": "Le réel $3$ s'écrit en notation scientifique binaire\n$3 = 1{,}1_2 \\times 2^{1}$. Dans le format simple précision,\nl'exposant n'est pas stocké tel quel : on lui ajoute $127$ avant de\nl'écrire sur huit bits. Quelle suite de huit bits est stockée dans\nce champ ?",
          "options": [
            {
              "text": "$00000001_2$",
              "correct": false,
              "feedback": "Erreur : $00000001_2 = 1$ est l'exposant **réel**, écrit sans lui\najouter $127$ comme le demande le format.\n"
            },
            {
              "text": "$01111110_2$",
              "correct": false,
              "feedback": "Erreur : $01111110_2 = 126$ ; on a soustrait $127$ au lieu de\nl'ajouter ($1 - 127 = -126$, puis on a oublié le signe). Le champ\ncontient $1 + 127 = 128$.\n"
            },
            {
              "text": "$10000001_2$",
              "correct": false,
              "feedback": "Erreur : $10000001_2 = 129$, soit $1 + 128$. Le décalage du format\nvaut $127$ et non $128$ : le champ contient $128$.\n"
            },
            {
              "text": "$10000000_2$",
              "correct": true,
              "feedback": "Bonne réponse : l'exposant stocké est $1 + 127 = 128 = 128 + 0$, ce\nqui s'écrit $10000000_2$ sur huit bits.\n"
            }
          ],
          "explanation": "Ajouter $127$ permet de ranger aussi les exposants négatifs dans un\nchamp de huit bits sans signe : un exposant réel $-1$ est stocké\n$126$. Pour relire l'exposant, on retire $127$ à la valeur stockée."
        }
      ]
    },
    {
      "id": "q29",
      "difficulty": 3,
      "skills": [
        "ieee",
        "decodage"
      ],
      "title": "Décoder un flottant simple précision",
      "partie": "ieee",
      "statement": "Un flottant est codé sur $32$ bits en simple précision :\n```\n0 | 10000001 | 01000000000000000000000\n```\nLe premier bit est le signe ; les $8$ bits suivants contiennent\nl'exposant augmenté de $127$ ; les $23$ derniers contiennent les\nchiffres après la virgule de la mantisse $1{,}\\ldots_2$, dont le\n$1$ de tête n'est pas stocké. Quelle est la valeur décimale\nreprésentée ?",
      "options": [
        {
          "text": "$1$",
          "correct": false,
          "feedback": "Erreur : on a oublié de rétablir le $1$ non stocké devant la\nvirgule. La mantisse vaut $1{,}01_2 = 1{,}25$ et non\n$0{,}01_2 = 0{,}25$ : la valeur est $1{,}25 \\times 2^{2} = 5$, pas\n$0{,}25 \\times 2^{2} = 1$.\n"
        },
        {
          "text": "$5$",
          "correct": true,
          "feedback": "Bonne réponse : signe `0` (positif), exposant\n$10000001_2 = 129$, donc $e = 129 - 127 = 2$. Mantisse\n$1{,}01_2 = 1{,}25$. Valeur : $1{,}25 \\times 2^{2} = 5$.\n"
        },
        {
          "text": "$10$",
          "correct": false,
          "feedback": "Erreur : $10 = 1{,}25 \\times 2^{3}$, l'exposant réel a été surestimé\nd'une unité. L'exposant stocké vaut $129$, donc $e = 2$ et le\nfacteur est $2^{2} = 4$, pas $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": "Décodage en trois étapes : lire le bit de signe ; lire l'exposant\nstocké $E$ et calculer $e = E - 127$ ; rétablir le $1$ devant les\nchiffres de la mantisse, puis calculer\n$(-1)^s \\times 1{,}M_2 \\times 2^e$. Ici :\n$(-1)^0 \\times 1{,}25 \\times 2^{2} = 5$.",
      "variants": [
        {
          "statement": "Un flottant est codé sur $32$ bits en simple précision :\n```\n0 | 10000001 | 01000000000000000000000\n```\nLe premier bit est le signe ; les $8$ bits suivants contiennent\nl'exposant augmenté de $127$ ; les $23$ derniers contiennent les\nchiffres après la virgule de la mantisse $1{,}\\ldots_2$, dont le\n$1$ de tête n'est pas stocké. Quelle est la valeur décimale\nreprésentée ?",
          "options": [
            {
              "text": "$1$",
              "correct": false,
              "feedback": "Erreur : on a oublié de rétablir le $1$ non stocké devant la\nvirgule. La mantisse vaut $1{,}01_2 = 1{,}25$ et non\n$0{,}01_2 = 0{,}25$ : la valeur est $1{,}25 \\times 2^{2} = 5$, pas\n$0{,}25 \\times 2^{2} = 1$.\n"
            },
            {
              "text": "$5$",
              "correct": true,
              "feedback": "Bonne réponse : signe `0` (positif), exposant\n$10000001_2 = 129$, donc $e = 129 - 127 = 2$. Mantisse\n$1{,}01_2 = 1{,}25$. Valeur : $1{,}25 \\times 2^{2} = 5$.\n"
            },
            {
              "text": "$10$",
              "correct": false,
              "feedback": "Erreur : $10 = 1{,}25 \\times 2^{3}$, l'exposant réel a été surestimé\nd'une unité. L'exposant stocké vaut $129$, donc $e = 2$ et le\nfacteur est $2^{2} = 4$, pas $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": "Décodage en trois étapes : lire le bit de signe ; lire l'exposant\nstocké $E$ et calculer $e = E - 127$ ; rétablir le $1$ devant les\nchiffres de la mantisse, puis calculer\n$(-1)^s \\times 1{,}M_2 \\times 2^e$. Ici :\n$(-1)^0 \\times 1{,}25 \\times 2^{2} = 5$."
        },
        {
          "statement": "Un flottant est codé sur $32$ bits en simple précision :\n```\n0 | 10000010 | 10000000000000000000000\n```\nLe premier bit est le signe ; les $8$ bits suivants contiennent\nl'exposant augmenté de $127$ ; les $23$ derniers contiennent les\nchiffres après la virgule de la mantisse $1{,}\\ldots_2$, dont le\n$1$ de tête n'est pas stocké. Quelle est la valeur décimale\nreprésentée ?",
          "options": [
            {
              "text": "$4$",
              "correct": false,
              "feedback": "Erreur : on a oublié de rétablir le $1$ non stocké devant la\nvirgule. La mantisse vaut $1{,}1_2 = 1{,}5$ et non\n$0{,}1_2 = 0{,}5$ : la valeur est $1{,}5 \\times 2^{3} = 12$, pas\n$0{,}5 \\times 2^{3} = 4$.\n"
            },
            {
              "text": "$12$",
              "correct": true,
              "feedback": "Bonne réponse : signe `0` (positif), exposant\n$10000010_2 = 130$, donc $e = 130 - 127 = 3$. Mantisse\n$1{,}1_2 = 1{,}5$. Valeur : $1{,}5 \\times 2^{3} = 12$.\n"
            },
            {
              "text": "$24$",
              "correct": false,
              "feedback": "Erreur : $24 = 1{,}5 \\times 2^{4}$, l'exposant réel a été surestimé\nd'une unité. L'exposant stocké vaut $130$, donc $e = 3$ et le\nfacteur est $2^{3} = 8$, pas $2^{4} = 16$.\n"
            },
            {
              "text": "$-12$",
              "correct": false,
              "feedback": "Erreur : le bit de signe vaut $0$ (positif). Le résultat\nest $+12$, pas $-12$.\n"
            }
          ],
          "explanation": "Décodage en trois étapes : lire le bit de signe ; lire l'exposant\nstocké $E$ et calculer $e = E - 127$ ; rétablir le $1$ devant les\nchiffres de la mantisse, puis calculer\n$(-1)^s \\times 1{,}M_2 \\times 2^e$. Ici :\n$(-1)^0 \\times 1{,}5 \\times 2^{3} = 12$."
        },
        {
          "statement": "Un flottant est codé sur $32$ bits en simple précision :\n```\n0 | 01111111 | 11000000000000000000000\n```\nLe premier bit est le signe ; les $8$ bits suivants contiennent\nl'exposant augmenté de $127$ ; les $23$ derniers contiennent les\nchiffres après la virgule de la mantisse $1{,}\\ldots_2$, dont le\n$1$ de tête n'est pas stocké. Quelle est la valeur décimale\nreprésentée ?",
          "options": [
            {
              "text": "$0{,}75$",
              "correct": false,
              "feedback": "Erreur : on a oublié de rétablir le $1$ non stocké devant la\nvirgule. La mantisse vaut $1{,}11_2 = 1{,}75$ et non\n$0{,}11_2 = 0{,}75$ : la valeur est $1{,}75 \\times 2^{0} = 1{,}75$, pas\n$0{,}75 \\times 2^{0} = 0{,}75$.\n"
            },
            {
              "text": "$1{,}75$",
              "correct": true,
              "feedback": "Bonne réponse : signe `0` (positif), exposant\n$01111111_2 = 127$, donc $e = 127 - 127 = 0$. Mantisse\n$1{,}11_2 = 1{,}75$. Valeur : $1{,}75 \\times 2^{0} = 1{,}75$.\n"
            },
            {
              "text": "$3{,}5$",
              "correct": false,
              "feedback": "Erreur : $3{,}5 = 1{,}75 \\times 2^{1}$, l'exposant réel a été surestimé\nd'une unité. L'exposant stocké vaut $127$, donc $e = 0$ et le\nfacteur est $2^{0} = 1$, pas $2^{1} = 2$.\n"
            },
            {
              "text": "$-1{,}75$",
              "correct": false,
              "feedback": "Erreur : le bit de signe vaut $0$ (positif). Le résultat\nest $+1{,}75$, pas $-1{,}75$.\n"
            }
          ],
          "explanation": "Décodage en trois étapes : lire le bit de signe ; lire l'exposant\nstocké $E$ et calculer $e = E - 127$ ; rétablir le $1$ devant les\nchiffres de la mantisse, puis calculer\n$(-1)^s \\times 1{,}M_2 \\times 2^e$. Ici :\n$(-1)^0 \\times 1{,}75 \\times 2^{0} = 1{,}75$."
        }
      ]
    },
    {
      "id": "q30",
      "difficulty": 1,
      "skills": [
        "ieee754",
        "double-precision",
        "structure"
      ],
      "title": "Répartition des bits d'un flottant double précision",
      "partie": "ieee",
      "statement": "Un `float` de Python suit le format double précision de la norme\nIEEE $754$, sur $64$ bits. Comment ces bits se répartissent-ils ?",
      "options": [
        {
          "text": "$1$ bit de signe, $11$ bits d'exposant, $52$ bits de mantisse",
          "correct": true,
          "feedback": "Bonne réponse : $1 + 11 + 52 = 64$. Les $52$ bits de mantisse,\ncomplétés par le $1$ implicite de tête, donnent environ seize\nchiffres décimaux significatifs.\n"
        },
        {
          "text": "$1$ bit de signe, $8$ bits d'exposant, $23$ bits de mantisse",
          "correct": false,
          "feedback": "Erreur : ces trois champs totalisent $32$ bits. C'est la\nrépartition de la simple précision, pas celle du `float` de\nPython.\n"
        },
        {
          "text": "$32$ bits pour la partie entière, $32$ bits pour la partie décimale",
          "correct": false,
          "feedback": "Erreur : ce découpage décrit une virgule fixe. Un flottant\nsépare signe, exposant et mantisse, ce qui permet à la virgule\nde se déplacer selon la grandeur du nombre.\n"
        },
        {
          "text": "$1$ bit de signe, $31$ bits d'exposant, $32$ bits de mantisse",
          "correct": false,
          "feedback": "Erreur : la somme fait bien $64$, mais l'exposant n'occupe que\n$11$ bits. La majeure partie du mot, $52$ bits, est réservée à\nla mantisse, qui fixe la précision.\n"
        }
      ],
      "explanation": "Simple précision : $1$, $8$ et $23$ bits sur $32$. Double précision :\n$1$, $11$ et $52$ bits sur $64$. Python utilise la seconde pour tous\nses `float`."
    },
    {
      "id": "q31",
      "difficulty": 2,
      "skills": [
        "ieee754",
        "double-precision",
        "exposant",
        "biais"
      ],
      "title": "Exposant biaisé en double précision",
      "partie": "ieee",
      "statement": "En double précision (norme IEEE $754$ sur $64$ bits), l'exposant\nest stocké sur $11$ bits, augmenté du biais $1023$. Quel champ\nd'exposant représente le réel $2^{5}$, c'est-à-dire\n$1{,}0_2 \\times 2^{5}$ ?",
      "options": [
        {
          "text": "$10000000100_2$",
          "correct": true,
          "feedback": "Bonne réponse : on stocke $5 + 1023 = 1028$, soit\n$10000000100_2$ sur onze bits.\n"
        },
        {
          "text": "$00000000101_2$",
          "correct": false,
          "feedback": "Erreur : l'exposant n'est pas stocké tel quel. Le biais permet\nde représenter aussi les exposants négatifs sans bit de signe\nsupplémentaire : il faut stocker $5 + 1023 = 1028$.\n"
        },
        {
          "text": "$01111111010_2$",
          "correct": false,
          "feedback": "Erreur : le biais s'ajoute à l'exposant, il ne s'en retranche\npas. La valeur $1023 - 5 = 1018$ représenterait\n$2^{-5}$.\n"
        },
        {
          "text": "$00010000100_2$",
          "correct": false,
          "feedback": "Erreur : $127$ est le biais de la simple précision, dont\nl'exposant tient sur $8$ bits. En double précision, le biais\nvaut $1023$ et $127 + 5 = 132$ n'a pas de sens.\n"
        }
      ],
      "explanation": "Le biais dépend de la taille du champ d'exposant : $127$ pour\n$8$ bits, $1023$ pour $11$ bits. Dans les deux cas, la valeur\nstockée est l'exposant réel augmenté du biais.",
      "variants": [
        {
          "statement": "En double précision (norme IEEE $754$ sur $64$ bits), l'exposant\nest stocké sur $11$ bits, augmenté du biais $1023$. Quel champ\nd'exposant représente le réel $2^{5}$, c'est-à-dire\n$1{,}0_2 \\times 2^{5}$ ?",
          "options": [
            {
              "text": "$10000000100_2$",
              "correct": true,
              "feedback": "Bonne réponse : on stocke $5 + 1023 = 1028$, soit\n$10000000100_2$ sur onze bits.\n"
            },
            {
              "text": "$00000000101_2$",
              "correct": false,
              "feedback": "Erreur : l'exposant n'est pas stocké tel quel. Le biais permet\nde représenter aussi les exposants négatifs sans bit de signe\nsupplémentaire : il faut stocker $5 + 1023 = 1028$.\n"
            },
            {
              "text": "$01111111010_2$",
              "correct": false,
              "feedback": "Erreur : le biais s'ajoute à l'exposant, il ne s'en retranche\npas. La valeur $1023 - 5 = 1018$ représenterait\n$2^{-5}$.\n"
            },
            {
              "text": "$00010000100_2$",
              "correct": false,
              "feedback": "Erreur : $127$ est le biais de la simple précision, dont\nl'exposant tient sur $8$ bits. En double précision, le biais\nvaut $1023$ et $127 + 5 = 132$ n'a pas de sens.\n"
            }
          ],
          "explanation": "Le biais dépend de la taille du champ d'exposant : $127$ pour\n$8$ bits, $1023$ pour $11$ bits. Dans les deux cas, la valeur\nstockée est l'exposant réel augmenté du biais."
        },
        {
          "statement": "En double précision (norme IEEE $754$ sur $64$ bits), l'exposant\nest stocké sur $11$ bits, augmenté du biais $1023$. Quel champ\nd'exposant représente le réel $2^{3}$, c'est-à-dire\n$1{,}0_2 \\times 2^{3}$ ?",
          "options": [
            {
              "text": "$10000000010_2$",
              "correct": true,
              "feedback": "Bonne réponse : on stocke $3 + 1023 = 1026$, soit\n$10000000010_2$ sur onze bits.\n"
            },
            {
              "text": "$00000000011_2$",
              "correct": false,
              "feedback": "Erreur : l'exposant n'est pas stocké tel quel. Le biais permet\nde représenter aussi les exposants négatifs sans bit de signe\nsupplémentaire : il faut stocker $3 + 1023 = 1026$.\n"
            },
            {
              "text": "$01111111100_2$",
              "correct": false,
              "feedback": "Erreur : le biais s'ajoute à l'exposant, il ne s'en retranche\npas. La valeur $1023 - 3 = 1020$ représenterait\n$2^{-3}$.\n"
            },
            {
              "text": "$00010000010_2$",
              "correct": false,
              "feedback": "Erreur : $127$ est le biais de la simple précision, dont\nl'exposant tient sur $8$ bits. En double précision, le biais\nvaut $1023$ et $127 + 3 = 130$ n'a pas de sens.\n"
            }
          ],
          "explanation": "Le biais dépend de la taille du champ d'exposant : $127$ pour\n$8$ bits, $1023$ pour $11$ bits. Dans les deux cas, la valeur\nstockée est l'exposant réel augmenté du biais."
        },
        {
          "statement": "En double précision (norme IEEE $754$ sur $64$ bits), l'exposant\nest stocké sur $11$ bits, augmenté du biais $1023$. Quel champ\nd'exposant représente le réel $2^{10}$, c'est-à-dire\n$1{,}0_2 \\times 2^{10}$ ?",
          "options": [
            {
              "text": "$10000001001_2$",
              "correct": true,
              "feedback": "Bonne réponse : on stocke $10 + 1023 = 1033$, soit\n$10000001001_2$ sur onze bits.\n"
            },
            {
              "text": "$00000001010_2$",
              "correct": false,
              "feedback": "Erreur : l'exposant n'est pas stocké tel quel. Le biais permet\nde représenter aussi les exposants négatifs sans bit de signe\nsupplémentaire : il faut stocker $10 + 1023 = 1033$.\n"
            },
            {
              "text": "$01111110101_2$",
              "correct": false,
              "feedback": "Erreur : le biais s'ajoute à l'exposant, il ne s'en retranche\npas. La valeur $1023 - 10 = 1013$ représenterait\n$2^{-10}$.\n"
            },
            {
              "text": "$00010001001_2$",
              "correct": false,
              "feedback": "Erreur : $127$ est le biais de la simple précision, dont\nl'exposant tient sur $8$ bits. En double précision, le biais\nvaut $1023$ et $127 + 10 = 137$ n'a pas de sens.\n"
            }
          ],
          "explanation": "Le biais dépend de la taille du champ d'exposant : $127$ pour\n$8$ bits, $1023$ pour $11$ bits. Dans les deux cas, la valeur\nstockée est l'exposant réel augmenté du biais."
        }
      ]
    },
    {
      "id": "q32",
      "difficulty": 3,
      "skills": [
        "ieee754",
        "mantisse",
        "precision"
      ],
      "title": "Écart entre deux flottants consécutifs",
      "partie": "ieee",
      "statement": "En simple précision, la mantisse compte $23$ chiffres binaires\naprès la virgule. Tous les flottants compris entre $2^{3}$ et\n$2^{4}$ partagent l'exposant $3$. Quel est l'écart entre deux\nflottants consécutifs de cet intervalle ?",
      "options": [
        {
          "text": "$2^{-20}$",
          "correct": true,
          "feedback": "Bonne réponse : dans cet intervalle, la valeur s'écrit\n$1{,}m_2 \\times 2^{3}$ et le dernier chiffre de la mantisse\npèse $2^{-23}$. Deux flottants consécutifs diffèrent donc de\n$2^{-23} \\times 2^{3} = 2^{-20}$.\n"
        },
        {
          "text": "$2^{-21}$",
          "correct": false,
          "feedback": "Erreur : le $1$ implicite de tête se trouve avant la virgule,\nil n'ajoute pas un vingt-quatrième chiffre après elle. Le\ndernier chiffre pèse $2^{-23}$, d'où un écart de $2^{-20}$.\n"
        },
        {
          "text": "$2^{-26}$",
          "correct": false,
          "feedback": "Erreur : l'exposant $3$ multiplie l'écart, il ne le divise\npas. Les flottants sont d'autant plus espacés qu'ils sont\ngrands : $2^{-23} \\times 2^{3} = 2^{-20}$.\n"
        },
        {
          "text": "$2^{-29}$",
          "correct": false,
          "feedback": "Erreur : les $32$ bits du codage ne sont pas tous des chiffres\nde la mantisse. Seuls les $23$ bits de mantisse fixent la\nprécision : l'écart vaut $2^{3 - 23} = 2^{-20}$.\n"
        }
      ],
      "explanation": "La précision d'un flottant est relative : l'écart entre deux\nvaleurs consécutives vaut $2^{-23}$ fois la puissance de deux de\nl'intervalle. Près de $1$, les flottants sont espacés d'environ\n$10^{-7}$ ; près de $10^{6}$, d'environ $0{,}06$.",
      "variants": [
        {
          "statement": "En simple précision, la mantisse compte $23$ chiffres binaires\naprès la virgule. Tous les flottants compris entre $2^{3}$ et\n$2^{4}$ partagent l'exposant $3$. Quel est l'écart entre deux\nflottants consécutifs de cet intervalle ?",
          "options": [
            {
              "text": "$2^{-20}$",
              "correct": true,
              "feedback": "Bonne réponse : dans cet intervalle, la valeur s'écrit\n$1{,}m_2 \\times 2^{3}$ et le dernier chiffre de la mantisse\npèse $2^{-23}$. Deux flottants consécutifs diffèrent donc de\n$2^{-23} \\times 2^{3} = 2^{-20}$.\n"
            },
            {
              "text": "$2^{-21}$",
              "correct": false,
              "feedback": "Erreur : le $1$ implicite de tête se trouve avant la virgule,\nil n'ajoute pas un vingt-quatrième chiffre après elle. Le\ndernier chiffre pèse $2^{-23}$, d'où un écart de $2^{-20}$.\n"
            },
            {
              "text": "$2^{-26}$",
              "correct": false,
              "feedback": "Erreur : l'exposant $3$ multiplie l'écart, il ne le divise\npas. Les flottants sont d'autant plus espacés qu'ils sont\ngrands : $2^{-23} \\times 2^{3} = 2^{-20}$.\n"
            },
            {
              "text": "$2^{-29}$",
              "correct": false,
              "feedback": "Erreur : les $32$ bits du codage ne sont pas tous des chiffres\nde la mantisse. Seuls les $23$ bits de mantisse fixent la\nprécision : l'écart vaut $2^{3 - 23} = 2^{-20}$.\n"
            }
          ],
          "explanation": "La précision d'un flottant est relative : l'écart entre deux\nvaleurs consécutives vaut $2^{-23}$ fois la puissance de deux de\nl'intervalle. Près de $1$, les flottants sont espacés d'environ\n$10^{-7}$ ; près de $10^{6}$, d'environ $0{,}06$."
        },
        {
          "statement": "En simple précision, la mantisse compte $23$ chiffres binaires\naprès la virgule. Tous les flottants compris entre $2^{10}$ et\n$2^{11}$ partagent l'exposant $10$. Quel est l'écart entre deux\nflottants consécutifs de cet intervalle ?",
          "options": [
            {
              "text": "$2^{-13}$",
              "correct": true,
              "feedback": "Bonne réponse : dans cet intervalle, la valeur s'écrit\n$1{,}m_2 \\times 2^{10}$ et le dernier chiffre de la mantisse\npèse $2^{-23}$. Deux flottants consécutifs diffèrent donc de\n$2^{-23} \\times 2^{10} = 2^{-13}$.\n"
            },
            {
              "text": "$2^{-14}$",
              "correct": false,
              "feedback": "Erreur : le $1$ implicite de tête se trouve avant la virgule,\nil n'ajoute pas un vingt-quatrième chiffre après elle. Le\ndernier chiffre pèse $2^{-23}$, d'où un écart de $2^{-13}$.\n"
            },
            {
              "text": "$2^{-33}$",
              "correct": false,
              "feedback": "Erreur : l'exposant $10$ multiplie l'écart, il ne le divise\npas. Les flottants sont d'autant plus espacés qu'ils sont\ngrands : $2^{-23} \\times 2^{10} = 2^{-13}$.\n"
            },
            {
              "text": "$2^{-22}$",
              "correct": false,
              "feedback": "Erreur : les $32$ bits du codage ne sont pas tous des chiffres\nde la mantisse. Seuls les $23$ bits de mantisse fixent la\nprécision : l'écart vaut $2^{10 - 23} = 2^{-13}$.\n"
            }
          ],
          "explanation": "La précision d'un flottant est relative : l'écart entre deux\nvaleurs consécutives vaut $2^{-23}$ fois la puissance de deux de\nl'intervalle. Près de $1$, les flottants sont espacés d'environ\n$10^{-7}$ ; près de $10^{6}$, d'environ $0{,}06$."
        },
        {
          "statement": "En simple précision, la mantisse compte $23$ chiffres binaires\naprès la virgule. Tous les flottants compris entre $2^{7}$ et\n$2^{8}$ partagent l'exposant $7$. Quel est l'écart entre deux\nflottants consécutifs de cet intervalle ?",
          "options": [
            {
              "text": "$2^{-16}$",
              "correct": true,
              "feedback": "Bonne réponse : dans cet intervalle, la valeur s'écrit\n$1{,}m_2 \\times 2^{7}$ et le dernier chiffre de la mantisse\npèse $2^{-23}$. Deux flottants consécutifs diffèrent donc de\n$2^{-23} \\times 2^{7} = 2^{-16}$.\n"
            },
            {
              "text": "$2^{-17}$",
              "correct": false,
              "feedback": "Erreur : le $1$ implicite de tête se trouve avant la virgule,\nil n'ajoute pas un vingt-quatrième chiffre après elle. Le\ndernier chiffre pèse $2^{-23}$, d'où un écart de $2^{-16}$.\n"
            },
            {
              "text": "$2^{-30}$",
              "correct": false,
              "feedback": "Erreur : l'exposant $7$ multiplie l'écart, il ne le divise\npas. Les flottants sont d'autant plus espacés qu'ils sont\ngrands : $2^{-23} \\times 2^{7} = 2^{-16}$.\n"
            },
            {
              "text": "$2^{-25}$",
              "correct": false,
              "feedback": "Erreur : les $32$ bits du codage ne sont pas tous des chiffres\nde la mantisse. Seuls les $23$ bits de mantisse fixent la\nprécision : l'écart vaut $2^{7 - 23} = 2^{-16}$.\n"
            }
          ],
          "explanation": "La précision d'un flottant est relative : l'écart entre deux\nvaleurs consécutives vaut $2^{-23}$ fois la puissance de deux de\nl'intervalle. Près de $1$, les flottants sont espacés d'environ\n$10^{-7}$ ; près de $10^{6}$, d'environ $0{,}06$."
        }
      ]
    },
    {
      "id": "q33",
      "difficulty": 2,
      "skills": [
        "comparaison",
        "egalite",
        "flottant"
      ],
      "title": "Trois fois un dixième",
      "partie": "consequences",
      "statement": "Que vaut `0.1 * 3 == 0.3` en Python ?",
      "options": [
        {
          "text": "`False`, le produit valant `0.30000000000000004`",
          "correct": true,
          "feedback": "Bonne réponse : ni $0{,}1$ ni $0{,}3$ ne sont représentables\nexactement en binaire. Les erreurs ne se compensent pas et le\nproduit diffère de `0.3` au seizième chiffre.\n"
        },
        {
          "text": "`True`, le calcul étant exact en décimal comme en binaire",
          "correct": false,
          "feedback": "Erreur : `0.1` est déjà une approximation de $0{,}1$ ; la\nmultiplier par $3$ ne redonne pas l'approximation de $0{,}3$.\n"
        },
        {
          "text": "Une erreur, un flottant ne pouvant être comparé avec `==`",
          "correct": false,
          "feedback": "Erreur : la comparaison est permise, elle est seulement peu\nfiable.\n"
        },
        {
          "text": "`0.3`, la valeur commune des deux membres",
          "correct": false,
          "feedback": "Erreur : une comparaison renvoie un booléen, et les deux membres\nne sont d'ailleurs pas égaux.\n"
        }
      ],
      "explanation": "Tester l'égalité de deux flottants est presque toujours une erreur.\nOn compare plutôt leur écart à une tolérance."
    },
    {
      "id": "q34",
      "difficulty": 3,
      "skills": [
        "boucle",
        "egalite",
        "flottant",
        "terminaison"
      ],
      "title": "Une boucle qui ne rencontre jamais un",
      "partie": "consequences",
      "statement": "Que se passe-t-il à l'exécution de ce programme ?\n```python\nx = 0\nwhile x != 1:\n    x = x + 0.1\nprint(\"fini\")\n```",
      "options": [
        {
          "text": "La boucle ne s'arrête jamais, `x` n'égalant jamais `1`",
          "correct": true,
          "feedback": "Bonne réponse : dix additions de `0.1` donnent\n`0.9999999999999999`, puis `x` dépasse $1$ sans jamais l'égaler.\nLa condition reste vraie indéfiniment.\n"
        },
        {
          "text": "Il affiche `fini` après dix tours, `x` valant alors exactement `1`",
          "correct": false,
          "feedback": "Erreur : après dix tours, `x` vaut `0.9999999999999999`, pas\n`1`.\n"
        },
        {
          "text": "Il affiche `fini` après onze tours, `x` dépassant alors `1`",
          "correct": false,
          "feedback": "Erreur : au onzième tour `x` vaut environ `1.0999999999999999`,\ntoujours différent de `1`.\n"
        },
        {
          "text": "Une erreur, `!=` n'acceptant pas un entier et un flottant",
          "correct": false,
          "feedback": "Erreur : la comparaison est valide ; le problème est qu'elle ne\ndevient jamais fausse.\n"
        }
      ],
      "explanation": "Une boucle `while` sur un flottant doit utiliser `<` ou `<=`, jamais\n`!=` ou `==` : l'égalité exacte n'est pas atteignable."
    },
    {
      "id": "q35",
      "difficulty": 3,
      "skills": [
        "troncature",
        "int",
        "flottant"
      ],
      "title": "Un entier qui n'est pas celui attendu",
      "partie": "consequences",
      "statement": "Que vaut `int((0.1 + 0.7) * 10)` en Python ?",
      "options": [
        {
          "text": "`7`, le produit valant `7.999999999999999`",
          "correct": true,
          "feedback": "Bonne réponse : `0.1 + 0.7` vaut `0.7999999999999999`, un peu\nmoins que $0{,}8$ ; multiplié par $10$, le résultat reste sous\n$8$, et `int` tronque à $7$.\n"
        },
        {
          "text": "`8`, le calcul tombant juste sur un entier",
          "correct": false,
          "feedback": "Erreur : le calcul tombe juste en décimal, pas en binaire. Le\nrésultat est légèrement inférieur à $8$.\n"
        },
        {
          "text": "`8.0`, `int` conservant un flottant",
          "correct": false,
          "feedback": "Erreur : `int` renvoie toujours un entier.\n"
        },
        {
          "text": "Une erreur, `int` ne s'appliquant qu'aux chaînes",
          "correct": false,
          "feedback": "Erreur : `int` accepte un flottant et le tronque.\n"
        }
      ],
      "explanation": "Tronquer un flottant proche d'un entier est un piège classique :\n`round` est plus sûr que `int` quand on attend une valeur entière."
    },
    {
      "id": "q36",
      "difficulty": 2,
      "skills": [
        "affichage",
        "representation",
        "flottant"
      ],
      "title": "Un affichage plus exact que la valeur stockée",
      "partie": "precision",
      "statement": "`0.1` n'est pas représentable exactement en binaire, et pourtant\n`print(0.1)` affiche `0.1`. Pourquoi ?",
      "options": [
        {
          "text": "Python affiche la plus courte écriture qui redonne le même flottant",
          "correct": true,
          "feedback": "Bonne réponse : la valeur stockée est\n$0{,}1000000000000000055\\ldots$, mais `0.1` suffit à la\ndésigner sans ambiguïté, et c'est cette écriture courte qui est\naffichée.\n"
        },
        {
          "text": "Parce que `0.1` est stocké exactement, contrairement à `0.3`",
          "correct": false,
          "feedback": "Erreur : aucun des deux n'est exact ; $0{,}1$ est une fraction\ndont le dénominateur n'est pas une puissance de $2$.\n"
        },
        {
          "text": "Parce que `print` arrondit toujours à un chiffre après la virgule",
          "correct": false,
          "feedback": "Erreur : `print(0.30000000000000004)` affiche bien dix-sept\nchiffres ; l'arrondi dépend de ce qui suffit à retrouver la\nvaleur.\n"
        },
        {
          "text": "Parce que l'erreur de représentation est corrigée à l'affichage",
          "correct": false,
          "feedback": "Erreur : rien n'est corrigé, la valeur stockée reste inexacte ;\nseule son écriture est raccourcie.\n"
        }
      ],
      "explanation": "L'affichage d'un flottant est une écriture décimale choisie pour\nêtre courte et sans ambiguïté. Il ne dit rien de l'exactitude de\nla valeur stockée."
    },
    {
      "id": "q37",
      "difficulty": 3,
      "skills": [
        "precision",
        "mantisse",
        "denombrement"
      ],
      "title": "Combien de flottants entre un et deux",
      "partie": "precision",
      "statement": "En double précision, la mantisse compte $52$ bits après la virgule.\nCombien de flottants distincts sont compris entre $1$ inclus et $2$\nexclu ?",
      "options": [
        {
          "text": "$2^{52}$, un par mantisse possible",
          "correct": true,
          "feedback": "Bonne réponse : entre $1$ et $2$, l'exposant est fixé à $0$ et\nseule la mantisse varie, sur $52$ bits : $2^{52}$ valeurs,\nrégulièrement espacées de $2^{-52}$.\n"
        },
        {
          "text": "Une infinité, comme pour les réels",
          "correct": false,
          "feedback": "Erreur : un flottant occupe $64$ bits, donc il n'existe qu'un\nnombre fini de valeurs, et une infinité de réels sont\ninaccessibles.\n"
        },
        {
          "text": "$2^{64}$, le nombre total de flottants",
          "correct": false,
          "feedback": "Erreur : $2^{64}$ est le nombre de mots de $64$ bits, répartis\nsur toutes les puissances de deux, pas seulement entre $1$ et\n$2$.\n"
        },
        {
          "text": "$1000$, un par millième entre les deux bornes",
          "correct": false,
          "feedback": "Erreur : le pas des flottants n'est pas décimal ; entre $1$ et\n$2$ il vaut $2^{-52}$, bien plus fin qu'un millième.\n"
        }
      ],
      "explanation": "Les flottants forment un ensemble fini et irrégulier : autant de\nvaleurs entre $1$ et $2$ qu'entre $1024$ et $2048$, mais bien plus\nespacées dans le second cas."
    },
    {
      "id": "q38",
      "difficulty": 3,
      "skills": [
        "virgule-fixe",
        "pas",
        "plage",
        "calcul"
      ],
      "title": "Pas et maximum d'une virgule fixe",
      "partie": "virgule",
      "statement": "Un nombre est codé en virgule fixe sur $8$ bits, dont $4$ pour la\npartie entière et $4$ pour la partie fractionnaire. Quel est\nl'écart entre deux valeurs consécutives, et quelle est la plus\ngrande valeur codable ?",
      "options": [
        {
          "text": "Un pas de $0{,}0625$ et un maximum de $15{,}9375$",
          "correct": true,
          "feedback": "Bonne réponse : le dernier bit fractionnaire pèse $2^{-4} =\n0{,}0625$, et le maximum, tous bits à $1$, vaut $2^{4} - 0{,}0625 =\n15{,}9375$.\n"
        },
        {
          "text": "Un pas de $0{,}25$ et un maximum de $15{,}9375$",
          "correct": false,
          "feedback": "Erreur : le pas est le poids du bit le plus à droite,\n$2^{-4}$, et non $1/4$.\n"
        },
        {
          "text": "Un pas de $0{,}0625$ et un maximum de $16$",
          "correct": false,
          "feedback": "Erreur : $16 = 2^{4}$ n'est pas codable : avec $4$\nbits entiers, le maximum est $2^{4}$ moins un pas.\n"
        },
        {
          "text": "Un pas de $1$ et un maximum de $255$",
          "correct": false,
          "feedback": "Erreur : ce serait un entier non signé sur $8$ bits, sans partie\nfractionnaire.\n"
        }
      ],
      "explanation": "En virgule fixe, le nombre de bits fractionnaires fixe la\nprécision, le nombre de bits entiers fixe la plage. Augmenter l'un\nréduit l'autre : c'est la limite que lève la virgule flottante.",
      "variants": [
        {
          "statement": "Un nombre est codé en virgule fixe sur $8$ bits, dont $4$ pour la\npartie entière et $4$ pour la partie fractionnaire. Quel est\nl'écart entre deux valeurs consécutives, et quelle est la plus\ngrande valeur codable ?",
          "options": [
            {
              "text": "Un pas de $0{,}0625$ et un maximum de $15{,}9375$",
              "correct": true,
              "feedback": "Bonne réponse : le dernier bit fractionnaire pèse $2^{-4} =\n0{,}0625$, et le maximum, tous bits à $1$, vaut $2^{4} - 0{,}0625 =\n15{,}9375$.\n"
            },
            {
              "text": "Un pas de $0{,}25$ et un maximum de $15{,}9375$",
              "correct": false,
              "feedback": "Erreur : le pas est le poids du bit le plus à droite,\n$2^{-4}$, et non $1/4$.\n"
            },
            {
              "text": "Un pas de $0{,}0625$ et un maximum de $16$",
              "correct": false,
              "feedback": "Erreur : $16 = 2^{4}$ n'est pas codable : avec $4$\nbits entiers, le maximum est $2^{4}$ moins un pas.\n"
            },
            {
              "text": "Un pas de $1$ et un maximum de $255$",
              "correct": false,
              "feedback": "Erreur : ce serait un entier non signé sur $8$ bits, sans partie\nfractionnaire.\n"
            }
          ],
          "explanation": "En virgule fixe, le nombre de bits fractionnaires fixe la\nprécision, le nombre de bits entiers fixe la plage. Augmenter l'un\nréduit l'autre : c'est la limite que lève la virgule flottante."
        },
        {
          "statement": "Un nombre est codé en virgule fixe sur $8$ bits, dont $5$ pour la\npartie entière et $3$ pour la partie fractionnaire. Quel est\nl'écart entre deux valeurs consécutives, et quelle est la plus\ngrande valeur codable ?",
          "options": [
            {
              "text": "Un pas de $0{,}125$ et un maximum de $31{,}875$",
              "correct": true,
              "feedback": "Bonne réponse : le dernier bit fractionnaire pèse $2^{-3} =\n0{,}125$, et le maximum, tous bits à $1$, vaut $2^{5} - 0{,}125 =\n31{,}875$.\n"
            },
            {
              "text": "Un pas de $0{,}3$ et un maximum de $31{,}875$",
              "correct": false,
              "feedback": "Erreur : le pas est le poids du bit le plus à droite,\n$2^{-3}$, et non $1/3$.\n"
            },
            {
              "text": "Un pas de $0{,}125$ et un maximum de $32$",
              "correct": false,
              "feedback": "Erreur : $32 = 2^{5}$ n'est pas codable : avec $5$\nbits entiers, le maximum est $2^{5}$ moins un pas.\n"
            },
            {
              "text": "Un pas de $1$ et un maximum de $255$",
              "correct": false,
              "feedback": "Erreur : ce serait un entier non signé sur $8$ bits, sans partie\nfractionnaire.\n"
            }
          ],
          "explanation": "En virgule fixe, le nombre de bits fractionnaires fixe la\nprécision, le nombre de bits entiers fixe la plage. Augmenter l'un\nréduit l'autre : c'est la limite que lève la virgule flottante."
        },
        {
          "statement": "Un nombre est codé en virgule fixe sur $8$ bits, dont $6$ pour la\npartie entière et $2$ pour la partie fractionnaire. Quel est\nl'écart entre deux valeurs consécutives, et quelle est la plus\ngrande valeur codable ?",
          "options": [
            {
              "text": "Un pas de $0{,}25$ et un maximum de $63{,}75$",
              "correct": true,
              "feedback": "Bonne réponse : le dernier bit fractionnaire pèse $2^{-2} =\n0{,}25$, et le maximum, tous bits à $1$, vaut $2^{6} - 0{,}25 =\n63{,}75$.\n"
            },
            {
              "text": "Un pas de $0{,}5$ et un maximum de $63{,}75$",
              "correct": false,
              "feedback": "Erreur : le pas est le poids du bit le plus à droite,\n$2^{-2}$, et non $1/2$.\n"
            },
            {
              "text": "Un pas de $0{,}25$ et un maximum de $64$",
              "correct": false,
              "feedback": "Erreur : $64 = 2^{6}$ n'est pas codable : avec $6$\nbits entiers, le maximum est $2^{6}$ moins un pas.\n"
            },
            {
              "text": "Un pas de $1$ et un maximum de $255$",
              "correct": false,
              "feedback": "Erreur : ce serait un entier non signé sur $8$ bits, sans partie\nfractionnaire.\n"
            }
          ],
          "explanation": "En virgule fixe, le nombre de bits fractionnaires fixe la\nprécision, le nombre de bits entiers fixe la plage. Augmenter l'un\nréduit l'autre : c'est la limite que lève la virgule flottante."
        }
      ]
    },
    {
      "id": "q39",
      "difficulty": 1,
      "skills": [
        "notation-scientifique",
        "type",
        "python"
      ],
      "title": "Une puissance de dix en Python",
      "partie": "virgule",
      "statement": "Que vaut `1e3` en Python ?",
      "options": [
        {
          "text": "`1000.0`, un flottant",
          "correct": true,
          "feedback": "Bonne réponse : `1e3` signifie $1 \\times 10^{3}$ et cette\nnotation produit toujours un flottant, même pour une valeur\nentière.\n"
        },
        {
          "text": "`1000`, un entier",
          "correct": false,
          "feedback": "Erreur : la notation avec `e` donne un `float`, pas un `int`.\n"
        },
        {
          "text": "`13`",
          "correct": false,
          "feedback": "Erreur : `e` ne concatène pas des chiffres, il introduit un\nexposant de $10$.\n"
        },
        {
          "text": "Une erreur, `e` n'étant pas un chiffre",
          "correct": false,
          "feedback": "Erreur : `1e3` est une écriture valide, la notation scientifique\nde Python.\n"
        }
      ],
      "explanation": "`3.5e-2` vaut $0{,}035$ et `6e23` vaut $6 \\times 10^{23}$ : la\nnotation scientifique s'écrit avec `e` et produit un flottant."
    },
    {
      "id": "q40",
      "difficulty": 2,
      "skills": [
        "consequences",
        "tolerance",
        "code"
      ],
      "title": "Écrire un test d'égalité avec tolérance",
      "partie": "consequences",
      "statement": "Quelle expression teste correctement que deux flottants `a` et `b`\nsont égaux à $10^{-9}$ près ?",
      "options": [
        {
          "text": "`abs(a - b) < 1e-9`",
          "correct": true,
          "feedback": "Bonne réponse : la valeur absolue rend le test symétrique, que\n`a` soit un peu au-dessus ou un peu en dessous de `b`.\n"
        },
        {
          "text": "`abs(a) - abs(b) < 1e-9`",
          "correct": false,
          "feedback": "Erreur : ce test compare des valeurs absolues ; $-1$ et $1$\npasseraient pour égaux.\n"
        },
        {
          "text": "`round(a) == round(b)`",
          "correct": false,
          "feedback": "Erreur : arrondir à l'entier confond $1{,}4$ et $0{,}6$.\n"
        },
        {
          "text": "`a == b` ou `a - b == 0`",
          "correct": false,
          "feedback": "Erreur : deux écritures du test exact, qui échoue sur\n$0{,}1 + 0{,}2$.\n"
        }
      ],
      "explanation": "Comparer des flottants, c'est comparer leur écart à un seuil ;\nla valeur absolue évite le piège du signe."
    },
    {
      "id": "q41",
      "difficulty": 2,
      "skills": [
        "consequences",
        "monnaie",
        "entiers"
      ],
      "title": "Calculer des montants sans erreur d'arrondi",
      "partie": "consequences",
      "statement": "Un programme de caisse additionne des prix en euros et des\ncentimes. Comment éviter les erreurs d'arrondi des flottants ?",
      "options": [
        {
          "text": "Compter en centimes avec des entiers, exacts par nature",
          "correct": true,
          "feedback": "Bonne réponse : $12{,}30$ € devient $1230$ centimes ; les\nadditions d'entiers sont exactes, et l'on ne divise par $100$\nqu'à l'affichage.\n"
        },
        {
          "text": "Arrondir le total à deux décimales après chaque addition",
          "correct": false,
          "feedback": "Erreur : chaque arrondi corrige un peu, mais les erreurs\npeuvent s'accumuler sur des milliers d'opérations.\n"
        },
        {
          "text": "Utiliser des flottants en double précision, plus précis",
          "correct": false,
          "feedback": "Erreur : les flottants de Python sont déjà en double précision,\net $0{,}1$ n'y est pas exact.\n"
        },
        {
          "text": "Convertir chaque prix en chaîne avant de l'additionner",
          "correct": false,
          "feedback": "Erreur : on ne peut pas additionner des chaînes.\n"
        }
      ],
      "explanation": "Dès qu'un calcul exige l'exactitude, argent, comptage, on choisit\nune unité entière plutôt qu'un flottant."
    },
    {
      "id": "q42",
      "difficulty": 2,
      "skills": [
        "ieee",
        "mantisse",
        "bit-implicite"
      ],
      "title": "Le bit caché de la mantisse",
      "partie": "ieee",
      "statement": "Un flottant normalisé s'écrit $1{,}m \\times 2^e$. Que devient le\n$1$ placé avant la virgule dans le codage IEEE 754 ?",
      "options": [
        {
          "text": "Il n'est pas stocké, étant toujours égal à $1$",
          "correct": true,
          "feedback": "Bonne réponse : seule la partie fractionnaire $m$ occupe les\nbits de mantisse ; le $1$ est sous-entendu, ce qui gagne un bit\nde précision.\n"
        },
        {
          "text": "Il est stocké en tête des bits de mantisse",
          "correct": false,
          "feedback": "Erreur : le stocker gaspillerait un bit toujours identique.\n"
        },
        {
          "text": "Il vaut $0$ pour les nombres négatifs",
          "correct": false,
          "feedback": "Erreur : le signe a son propre bit, la mantisse est la même.\n"
        },
        {
          "text": "Il est ajouté à l'exposant",
          "correct": false,
          "feedback": "Erreur : l'exposant ne code que la puissance de deux.\n"
        }
      ],
      "explanation": "Sous forme normalisée, le chiffre avant la virgule est toujours\n$1$ en binaire : inutile de l'écrire, la norme le sous-entend."
    },
    {
      "id": "q43",
      "difficulty": 1,
      "skills": [
        "ieee",
        "signe",
        "bit"
      ],
      "title": "Le bit de signe d'un flottant",
      "partie": "ieee",
      "statement": "Comment le signe d'un flottant est-il codé en IEEE 754 ?",
      "options": [
        {
          "text": "Par un seul bit, $1$ pour un nombre négatif",
          "correct": true,
          "feedback": "Bonne réponse : le premier bit du codage vaut $0$ pour un\npositif et $1$ pour un négatif ; mantisse et exposant codent la\nvaleur absolue.\n"
        },
        {
          "text": "Par le complément à deux de la mantisse",
          "correct": false,
          "feedback": "Erreur : le complément à deux concerne les entiers, pas les\nflottants.\n"
        },
        {
          "text": "Par un seul bit, $1$ pour un nombre positif",
          "correct": false,
          "feedback": "Erreur : la convention est inverse, $1$ signale un négatif.\n"
        },
        {
          "text": "Par le signe de l'exposant",
          "correct": false,
          "feedback": "Erreur : l'exposant dit si le nombre est grand ou petit, pas\ns'il est négatif.\n"
        }
      ],
      "explanation": "Signe, exposant, mantisse : les trois champs d'un flottant, le\npremier ne prenant qu'un bit."
    }
  ]
}