{
  "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, valeurs exactes ou approchées de 0,1,\n0,25 et 1/3, précision et erreurs d'arrondi, conséquences pratiques sur les calculs.",
    "parties": [
      {
        "id": "virgule",
        "title": "Virgule fixe et virgule flottante"
      },
      {
        "id": "ieee",
        "title": "Valeurs exactes et approchées"
      },
      {
        "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$."
        },
        {
          "statement": "Quelle est l'écriture en base $2$ du nombre décimal $0{,}625$ ?",
          "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{,}625$ est plus petit\nqu'un demi.\n"
            },
            {
              "text": "$0{,}101_2$",
              "correct": true,
              "feedback": "Bonne réponse : $0{,}625 = \\frac{5}{8} = \\frac{1}{2} + \\frac{1}{8}$. On a\n$0{,}625 \\times 2 = 1{,}25$ (chiffre $1$), 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{,}625$ est plus petit qu'un demi.\n"
            },
            {
              "text": "$0{,}625_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{,}625 = \\frac{5}{8} = \\frac{1}{2} + \\frac{1}{8}$,\nson écriture binaire est finie et courte : $0{,}101_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$."
        },
        {
          "statement": "Quelle est la valeur décimale du nombre écrit en base $2$ :\n$110{,}101_2$ ?",
          "options": [
            {
              "text": "$6{,}101$",
              "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{,}101_2$ vaut\n$0{,}625$.\n"
            },
            {
              "text": "$6{,}5$",
              "correct": false,
              "feedback": "Erreur : $0{,}101_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{,}625$.\n"
            },
            {
              "text": "$6{,}625$",
              "correct": true,
              "feedback": "Bonne réponse : $110_2 = 4 + 2 = 6$ et\n$0{,}101_2 = 1 \\times \\frac{1}{2} + 0 \\times \\frac{1}{4} + 1 \\times \\frac{1}{8} = 0{,}625$,\nsoit $6{,}625$.\n"
            },
            {
              "text": "$3{,}625$",
              "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}{2} + \\frac{1}{8} = 6{,}625$."
        }
      ]
    },
    {
      "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$."
        },
        {
          "statement": "En Python, l'instruction `float(25)` renvoie :",
          "options": [
            {
              "text": "`25` (entier inchangé)",
              "correct": false,
              "feedback": "Erreur : la fonction `float` change le type. Le\nrésultat est `25.0`, qui est un flottant.\n"
            },
            {
              "text": "`25.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": "`'25'` (chaîne de caractères)",
              "correct": false,
              "feedback": "Erreur : `float()` convertit en flottant, pas en\nchaîne. Pour une chaîne, on utiliserait `str(25)`.\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": [
        "conversion",
        "binaire"
      ],
      "title": "Les premiers chiffres binaires de 0,1",
      "partie": "ieee",
      "statement": "On écrit $0{,}1$ en base $2$ en multipliant la partie\ndécimale par $2$ et en notant à chaque fois la partie\nentière obtenue. Quels sont les **six premiers chiffres**\naprès la virgule ?",
      "options": [
        {
          "text": "$0{,}000111_2$",
          "correct": false,
          "feedback": "Erreur : le sixième produit est $0{,}2 \\times 2 = 0{,}4$,\ndont la partie entière est $0$, pas $1$.\n"
        },
        {
          "text": "$0{,}001100_2$",
          "correct": false,
          "feedback": "Erreur : il manque un $0$ au début ; $0{,}1 \\times 2$,\n$0{,}2 \\times 2$ et $0{,}4 \\times 2$ donnent trois\nchiffres $0$.\n"
        },
        {
          "text": "$0{,}000110_2$",
          "correct": true,
          "feedback": "Bonne réponse : $0{,}2$ (0), $0{,}4$ (0), $0{,}8$ (0),\n$1{,}6$ (1), $1{,}2$ (1), $0{,}4$ (0).\n"
        },
        {
          "text": "$0{,}000101_2$",
          "correct": false,
          "feedback": "Erreur : après $1{,}6$, on garde $0{,}6$, et\n$0{,}6 \\times 2 = 1{,}2$ donne encore un chiffre $1$.\n"
        }
      ],
      "explanation": "Après le sixième chiffre, on retrouve $0{,}4$, déjà\nrencontré : les chiffres $0011$ se répètent sans fin,\n$0{,}1 = 0{,}0\\,0011\\,0011\\,0011\\ldots_2$. Un flottant n'en\ngarde qu'un nombre fini."
    },
    {
      "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}$."
        },
        {
          "statement": "Quelle est l'écriture binaire de $3{,}125$ ?",
          "options": [
            {
              "text": "$111{,}001$",
              "correct": false,
              "feedback": "Erreur : $111_2 = 7$, pas $3$. Confusion sur la partie\nentière : $3 = 2 + 1 = 11_2$.\n"
            },
            {
              "text": "$11{,}125$",
              "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": "$11{,}100$",
              "correct": false,
              "feedback": "Erreur : $0{,}100_2$ vaut $0{,}5$, ce qui ne correspond pas\nà $0{,}125$. Il faut poursuivre les multiplications par $2$\njusqu'à épuiser la partie fractionnaire.\n"
            },
            {
              "text": "$11{,}001$",
              "correct": true,
              "feedback": "Bonne réponse : la partie entière donne $3 = 11_2$. La\npartie fractionnaire se calcule par multiplications\nsuccessives par $2$ : $0{,}125 \\times 2 = 0{,}25$ (bit $0$), puis $0{,}25 \\times 2 = 0{,}5$ (bit $0$), puis $0{,}5 \\times 2 = 1{,}0$ (bit $1$). On obtient\n$0{,}001_2$, d'où $11{,}001_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{,}125$, on\nobtient $0{,}001_2$ exactement, car $0{,}125 = 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": [
        "conversion",
        "binaire"
      ],
      "title": "Un tiers écrit en base deux",
      "partie": "ieee",
      "statement": "En appliquant la méthode des multiplications par $2$ à\n$\\frac{1}{3}$, quelle écriture binaire obtient-on ?",
      "options": [
        {
          "text": "$0{,}0101\\ldots_2$, le motif $01$ se répétant sans fin",
          "correct": true,
          "feedback": "Bonne réponse : $\\frac{2}{3}$ (0), puis\n$\\frac{4}{3}$ (1, reste $\\frac{1}{3}$), et l'on\nrevient au départ.\n"
        },
        {
          "text": "$0{,}0110\\ldots_2$, le motif $011$ se répétant sans fin",
          "correct": false,
          "feedback": "Erreur : après le chiffre $1$, il reste $\\frac{1}{3}$ ;\nle chiffre suivant est donc $0$, pas $1$.\n"
        },
        {
          "text": "$0{,}0101_2$ exactement, sur quatre chiffres",
          "correct": false,
          "feedback": "Erreur : $0{,}0101_2 = 0{,}3125$, qui n'est qu'une valeur\napprochée de $\\frac{1}{3}$ ; le calcul ne s'arrête jamais.\n"
        },
        {
          "text": "$0{,}0011_2$ exactement, sur quatre chiffres",
          "correct": false,
          "feedback": "Erreur : $0{,}0011_2 = 0{,}1875$, bien loin de\n$\\frac{1}{3}$ ; le premier produit $\\frac{2}{3}$ donne\n$0$, le deuxième $\\frac{4}{3}$ donne déjà $1$.\n"
        }
      ],
      "explanation": "$\\frac{1}{3}$ n'a d'écriture finie ni en base $10$\n($0{,}333\\ldots$) ni en base $2$ ($0{,}0101\\ldots_2$) : un\nflottant ne peut en stocker qu'une valeur approchée."
    },
    {
      "id": "q29",
      "difficulty": 3,
      "skills": [
        "conversion",
        "binaire",
        "approximation"
      ],
      "title": "Arrondir 0,1 sur quatre chiffres binaires",
      "partie": "ieee",
      "statement": "Une machine ne garde que **quatre chiffres binaires** après la\nvirgule. Parmi les nombres qu'elle peut représenter, lequel est\nle plus proche de $0{,}1$ ?",
      "options": [
        {
          "text": "$0{,}0625$, soit $0{,}0001_2$",
          "correct": false,
          "feedback": "Erreur : c'est la troncature de $0{,}1$, à $0{,}0375$ de lui ;\n$0{,}125$ n'en est qu'à $0{,}025$.\n"
        },
        {
          "text": "$0{,}1$, soit $0{,}0001_2$ exactement",
          "correct": false,
          "feedback": "Erreur : $0{,}0001_2$ vaut $\\frac{1}{16} = 0{,}0625$ ; $0{,}1$\nn'a pas d'écriture binaire finie.\n"
        },
        {
          "text": "$0{,}125$, soit $0{,}0010_2$",
          "correct": true,
          "feedback": "Bonne réponse : avec quatre chiffres, les valeurs vont de\n$0{,}0625$ en $0{,}0625$ ; $0{,}125$ est la plus proche de\n$0{,}1$.\n"
        },
        {
          "text": "$0{,}25$, soit $0{,}0100_2$",
          "correct": false,
          "feedback": "Erreur : $0{,}25$ est à $0{,}15$ de $0{,}1$, bien plus loin que\n$0{,}125$.\n"
        }
      ],
      "explanation": "Une machine qui arrondit au plus proche ne tronque pas : la valeur\nstockée peut être plus grande que le nombre de départ. Les\nflottants de Python arrondissent ainsi, sur $52$ chiffres."
    },
    {
      "id": "q30",
      "difficulty": 1,
      "skills": [
        "comparaison",
        "exactitude"
      ],
      "title": "Une égalité de flottants qui tient",
      "partie": "ieee",
      "statement": "Laquelle de ces expressions Python vaut `True` ?",
      "options": [
        {
          "text": "`0.1 + 0.2 == 0.3`",
          "correct": false,
          "feedback": "Erreur : `0.1` et `0.2` sont approchés en binaire, la\nsomme vaut `0.30000000000000004`.\n"
        },
        {
          "text": "`0.7 + 0.1 == 0.8`",
          "correct": false,
          "feedback": "Erreur : `0.7 + 0.1` vaut `0.7999999999999999`, à cause\ndes approximations de `0.7` et de `0.1`.\n"
        },
        {
          "text": "`1.5 - 0.25 == 1.25`",
          "correct": true,
          "feedback": "Bonne réponse : $1{,}5 = 2^0 + 2^{-1}$ et $0{,}25 = 2^{-2}$\nsont représentés exactement, la différence aussi.\n"
        },
        {
          "text": "`0.1 * 3 == 0.3`",
          "correct": false,
          "feedback": "Erreur : `0.1 * 3` vaut `0.30000000000000004`, l'erreur\nsur `0.1` est multipliée par trois.\n"
        }
      ],
      "explanation": "Un calcul sur des sommes de puissances de $2$ ($0{,}5$,\n$0{,}25$, $0{,}125$) reste exact ; dès qu'un nombre comme\n$0{,}1$ intervient, le résultat n'est qu'approché."
    },
    {
      "id": "q31",
      "difficulty": 2,
      "skills": [
        "approximation",
        "affichage"
      ],
      "title": "Afficher un tiers en Python",
      "partie": "ieee",
      "statement": "Que produit l'instruction `print(1 / 3)` ?",
      "options": [
        {
          "text": "`0.3333333333333333`, une valeur approchée",
          "correct": true,
          "feedback": "Bonne réponse : le flottant ne garde qu'un nombre fini de\nchiffres binaires, Python en affiche environ seize\nchiffres décimaux.\n"
        },
        {
          "text": "`0.333…`, avec des chiffres qui défilent sans fin",
          "correct": false,
          "feedback": "Erreur : un flottant occupe $64$ bits ; il ne peut pas\ncontenir une infinité de chiffres.\n"
        },
        {
          "text": "`1/3`, la fraction exacte gardée en mémoire",
          "correct": false,
          "feedback": "Erreur : l'opérateur `/` renvoie un `float`, jamais une\nfraction.\n"
        },
        {
          "text": "`0.33`, la valeur arrondie au centième",
          "correct": false,
          "feedback": "Erreur : Python n'arrondit pas l'affichage à deux\nchiffres, sauf si on le lui demande avec `round`.\n"
        }
      ],
      "explanation": "$\\frac{1}{3}$ n'a pas d'écriture finie en base $2$ : le\nflottant stocké en est une valeur approchée, et l'affichage\nle montre."
    },
    {
      "id": "q32",
      "difficulty": 3,
      "skills": [
        "approximation",
        "binaire"
      ],
      "title": "Approcher un tiers sur quatre chiffres binaires",
      "partie": "ieee",
      "statement": "On ne dispose que de **quatre chiffres binaires** après la\nvirgule et l'on tronque l'écriture de $\\frac{1}{3}$, qui\ncommence par $0{,}0101\\,0101\\ldots_2$. Quelle valeur\ndécimale obtient-on ?",
      "options": [
        {
          "text": "$0{,}375$",
          "correct": false,
          "feedback": "Erreur : c'est $0{,}0110_2$, une valeur plus grande que\n$\\frac{1}{3}$ ; tronquer donne toujours une valeur plus\npetite.\n"
        },
        {
          "text": "$0{,}3125$",
          "correct": true,
          "feedback": "Bonne réponse : $0{,}0101_2 = \\frac{1}{4} + \\frac{1}{16}\n= 0{,}3125$, à environ $0{,}02$ de $\\frac{1}{3}$.\n"
        },
        {
          "text": "$0{,}1875$",
          "correct": false,
          "feedback": "Erreur : c'est $0{,}0011_2$ ; les chiffres ont été pris\ndans le mauvais ordre.\n"
        },
        {
          "text": "$0{,}625$",
          "correct": false,
          "feedback": "Erreur : c'est $0{,}1010_2$ ; le premier chiffre après la\nvirgule de $\\frac{1}{3}$ est $0$.\n"
        }
      ],
      "explanation": "Avec quatre chiffres, l'erreur peut atteindre\n$2^{-4} = 0{,}0625$ ; un `float`, avec ses $52$ chiffres,\nramène l'erreur vers $10^{-17}$, sans l'annuler."
    },
    {
      "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."
        },
        {
          "statement": "Un nombre est codé en virgule fixe sur $8$ bits, dont $3$ pour la\npartie entière et $5$ 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{,}03125$ et un maximum de $7{,}96875$",
              "correct": true,
              "feedback": "Bonne réponse : le dernier bit fractionnaire pèse $2^{-5} =\n0{,}03125$, et le maximum, tous bits à $1$, vaut $2^{3} - 0{,}03125 =\n7{,}96875$.\n"
            },
            {
              "text": "Un pas de $0{,}2$ et un maximum de $7{,}96875$",
              "correct": false,
              "feedback": "Erreur : le pas est le poids du bit le plus à droite,\n$2^{-5}$, et non $1/5$.\n"
            },
            {
              "text": "Un pas de $0{,}03125$ et un maximum de $8$",
              "correct": false,
              "feedback": "Erreur : $8 = 2^{3}$ n'est pas codable : avec $3$\nbits entiers, le maximum est $2^{3}$ 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.",
      "variants": [
        {
          "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."
        },
        {
          "statement": "Que vaut `1e2` en Python ?",
          "options": [
            {
              "text": "`100.0`, un flottant",
              "correct": true,
              "feedback": "Bonne réponse : `1e2` signifie $1 \\times 10^{2}$ et cette\nnotation produit toujours un flottant, même pour une valeur\nentière.\n"
            },
            {
              "text": "`100`, un entier",
              "correct": false,
              "feedback": "Erreur : la notation avec `e` donne un `float`, pas un `int`.\n"
            },
            {
              "text": "`12`",
              "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 : `1e2` 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."
        },
        {
          "statement": "Que vaut `1e4` en Python ?",
          "options": [
            {
              "text": "`10000.0`, un flottant",
              "correct": true,
              "feedback": "Bonne réponse : `1e4` signifie $1 \\times 10^{4}$ et cette\nnotation produit toujours un flottant, même pour une valeur\nentière.\n"
            },
            {
              "text": "`10000`, un entier",
              "correct": false,
              "feedback": "Erreur : la notation avec `e` donne un `float`, pas un `int`.\n"
            },
            {
              "text": "`14`",
              "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 : `1e4` 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."
        },
        {
          "statement": "Que vaut `1e6` en Python ?",
          "options": [
            {
              "text": "`1000000.0`, un flottant",
              "correct": true,
              "feedback": "Bonne réponse : `1e6` signifie $1 \\times 10^{6}$ et cette\nnotation produit toujours un flottant, même pour une valeur\nentière.\n"
            },
            {
              "text": "`1000000`, un entier",
              "correct": false,
              "feedback": "Erreur : la notation avec `e` donne un `float`, pas un `int`.\n"
            },
            {
              "text": "`16`",
              "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 : `1e6` 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": [
        "exactitude",
        "binaire"
      ],
      "title": "Lesquels sont représentés exactement",
      "partie": "ieee",
      "statement": "Parmi $0{,}1$, $0{,}25$ et $\\frac{1}{3}$, lesquels un\nflottant représente-t-il **exactement** ?",
      "options": [
        {
          "text": "Aucun, un flottant n'étant jamais qu'une valeur approchée",
          "correct": false,
          "feedback": "Erreur : les nombres qui s'écrivent avec un nombre fini\nde chiffres binaires, comme $0{,}25$, sont stockés sans\nerreur.\n"
        },
        {
          "text": "$0{,}1$ et $0{,}25$, qui s'écrivent avec peu de décimales",
          "correct": false,
          "feedback": "Erreur : une écriture décimale finie ne suffit pas ;\n$0{,}1$ a une écriture binaire infinie.\n"
        },
        {
          "text": "Les trois, puisqu'un flottant occupe 64 bits",
          "correct": false,
          "feedback": "Erreur : $0{,}1$ et $\\frac{1}{3}$ demanderaient une\ninfinité de chiffres binaires ; $64$ bits n'y suffisent\npas.\n"
        },
        {
          "text": "$0{,}25$ seulement, qui vaut une puissance de 2",
          "correct": true,
          "feedback": "Bonne réponse : $0{,}25 = 2^{-2} = 0{,}01_2$ ; les deux\nautres ont une écriture binaire infinie.\n"
        }
      ],
      "explanation": "Un réel est représenté exactement quand il s'écrit comme\nune somme finie de puissances de $2$ (dans les limites du\nformat) : $0{,}25$, $0{,}5$ ou $0{,}375$ le sont, pas\n$0{,}1$ ni $\\frac{1}{3}$."
    },
    {
      "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."
    }
  ]
}