# -*- coding: utf-8 -*- """ Corrigé Python - Bac NSI 2026 - Épreuve pratique - Sujet 8 Thème : addition en BCD et problème des flottants """ from __future__ import annotations def calcul_recettes() -> float: """ Additionne le prix de tous les menus vendus dans la journée. On obtient un résultat très proche de 4 635 000, mais pas toujours exactement égal, car les nombres flottants comme 2.27, 5.19 ou 1.81 ne sont pas représentés exactement en binaire. """ prix_menu = 2.27 + 5.19 + 1.81 total = 0.0 for _ in range(1000 * 500): total += prix_menu return total def convertir_BCD_vers_decimal(liste_quartets: list[str]) -> float: """ Convertit une liste de quartets BCD en nombre décimal. Convention : la virgule est implicite avant les deux derniers chiffres. Exemple : ['0001', '0011', '0101', '0110'] représente 13.56. """ chiffres = "" for quartet in liste_quartets: chiffres += str(int(quartet, 2)) return int(chiffres) / 100 def convertir_dec_vers_BCD(decimal: str) -> list[str]: """ Convertit une chaîne représentant un nombre décimal vers une liste de quartets BCD. Convention : virgule implicite avant les deux derniers quartets. """ ajouter_zero = False liste_quartets = [] if "." not in decimal: decimal = decimal + ".00" for i in range(len(decimal)): if decimal[i] != ".": quartet = bin(int(decimal[i]))[2:].zfill(4) liste_quartets.append(quartet) if decimal[i] == "." and i == len(decimal) - 2: ajouter_zero = True if ajouter_zero: liste_quartets.append("0000") return liste_quartets def additionner_binaire_quartets(quartet1: str, quartet2: str, retenue: int) -> tuple[str, int]: """ Additionne bit à bit deux quartets binaires purs. Renvoie un tuple (somme_binaire, nouvelle_retenue). """ somme = "" for i in range(4): bit1 = int(quartet1[3 - i]) bit2 = int(quartet2[3 - i]) total = bit1 + bit2 + retenue somme = str(total % 2) + somme retenue = total // 2 return somme, retenue def corriger_BCD(somme: str, retenue: int) -> tuple[str, int]: """ Applique la correction BCD si le quartet dépasse 9 ou si une retenue est produite. On ajoute alors 6, c'est-à-dire '0110'. """ valeur = int(somme, 2) if valeur >= 10 or retenue == 1: somme_corrigee, retenue_correction = additionner_binaire_quartets(somme, "0110", 0) return somme_corrigee, max(retenue, retenue_correction) return somme, retenue def aligner_quartets(q1: list[str], q2: list[str]) -> tuple[list[str], list[str]]: """ Ajoute des quartets '0000' au début de la liste la plus courte pour que les deux nombres aient la même longueur. """ q1 = q1.copy() q2 = q2.copy() while len(q1) < len(q2): q1.insert(0, "0000") while len(q2) < len(q1): q2.insert(0, "0000") return q1, q2 def additionner_nombres_format_BCD(a: str, b: str) -> list[str]: """ Additionne deux nombres représentés sous forme décimale, en passant par le format BCD. """ liste_quartets1 = convertir_dec_vers_BCD(a) liste_quartets2 = convertir_dec_vers_BCD(b) liste_quartets1, liste_quartets2 = aligner_quartets(liste_quartets1, liste_quartets2) retenue = 0 resultat = [] longueur = len(liste_quartets1) for i in range(longueur - 1, -1, -1): somme, retenue = additionner_binaire_quartets(liste_quartets1[i], liste_quartets2[i], retenue) somme, retenue = corriger_BCD(somme, retenue) resultat.insert(0, somme) if retenue == 1: resultat.insert(0, "0001") return resultat def tests() -> None: assert round(convertir_BCD_vers_decimal(["0001", "0011", "0101", "0110"]), 2) == 13.56 assert convertir_BCD_vers_decimal(additionner_nombres_format_BCD("27", "35")) == 62.0 assert convertir_BCD_vers_decimal(additionner_nombres_format_BCD("23", "4")) == 27.0 assert convertir_BCD_vers_decimal(additionner_nombres_format_BCD("1.75", "0.23")) == 1.98 print("Tous les tests du sujet 8 sont passés.") if __name__ == "__main__": print("Recettes calculées avec des flottants :", calcul_recettes()) tests()