Maths & NSI

Baccalauréat — Épreuve pratique — 2026 — NSI

Épreuve pratique NSI 2026 — Sujet 08 : calculs monétaires, flottants et codage BCD

Sujet

Épreuve pratique de NSI, session 2026 — sujet n°08 de la banque nationale. Durée : 1 heure, sur ordinateur. Le candidat dispose de l'énoncé et de fichiers de code et de données ; il agit en autonomie et, aux « appels professeur » indiqués, présente son travail à l'examinateur ou le sollicite en cas de difficulté.

Calculs monétaires et codage BCD

En informatique, utiliser des nombres flottants pour manipuler des valeurs monétaires est une erreur de conception classique. Les ordinateurs utilisant le système binaire (base 2), certains nombres décimaux comme 0.1 ne peuvent pas être représentés de manière exacte et génèrent une infinité de décimales dans leur représentation binaire flottante (0.00011001100110011…). Lors de calculs financiers, ces erreurs d'arrondi s'accumulent et faussent les bilans comptables.

Question 1. La chaîne de restauration « RESTO NSI » comprend 1 000 restaurants qui délivrent chacun 500 menus par jour. Un menu est composé d'une entrée à 2.27 €, d'un plat à 5.19 € et d'un dessert à 1.81 €. Écrire, dans le fichier addition_BCD.py, une fonction calcul_recettes() qui additionne le prix de chaque menu vendu dans la journée en utilisant une boucle. Afficher le résultat de cette fonction. Sachant que la valeur théorique exacte est de 4 635 000 €, justifier le comportement observé.

Appel professeur — Appeler le professeur pour lui présenter votre réponse ou en cas de difficulté.

Historiquement, pour pallier ce problème dans les calculatrices et les systèmes financiers, on utilise le système BCD (Binary Coded Decimal). Le principe est de coder chaque chiffre du nombre décimal séparément sur 4 bits (un quartet). La virgule n'étant pas codée, on utilise la convention monétaire « virgule implicite deux rangs avant la fin ». Il faut donc au minimum 3 quartets pour représenter une somme.

Montant en eurosReprésentation BCD (listes de chaînes)
59.00['0101', '1001', '0000', '0000']
1.75['0001', '0111', '0101']
0.23['0000', '0010', '0011']

Le fichier addition_BCD.py contient des fonctions permettant de manipuler ces données.

Question 2. Écrire la fonction convertir_BCD_vers_decimal(liste_quartets) qui prend en paramètre une liste de chaînes de caractères représentant des quartets BCD, et renvoie la valeur décimale correspondante (de type float). Ajouter une assertion pour vérifier que convertir_BCD_vers_decimal(['0001', '0011', '0101', '0110']) renvoie bien la valeur 13.56.

Indication : on pourra utiliser le fait que int(s, 2) renvoie le nombre dont l'écriture binaire est donnée par la chaîne de caractères s.

Appel professeur — Appeler le professeur pour lui présenter votre réponse ou en cas de difficulté.

Afin de réaliser une addition de deux nombres donnés en BCD, on additionne les nombres quartet par quartet, de droite à gauche. Si le résultat d'une addition binaire de quartets est supérieur ou égal à 10 (soit '1010' en binaire) ou s'il génère une retenue, le format BCD n'est plus valide. Il faut alors appliquer une correction en ajoutant 6 (soit '0110') à ce quartet et propager la retenue.

Question 3. La fonction additionner_nombres_format_BCD(a, b) fournie dans le fichier réalise cette addition. L'évaluation de l'appel additionner_nombres_format_BCD('27', '35') devrait correspondre à 62, mais la liste renvoyée est fausse. Analyser le code fourni. Identifier l'oubli de l'étape de correction dans l'algorithme, puis insérer un appel à la fonction corriger_BCD (déjà fournie) au bon endroit pour résoudre ce problème. Refaire le test pour valider la réparation.

Appel professeur — Appeler le professeur pour lui présenter votre réponse ou en cas de difficulté.

Question 4. Tester maintenant l'addition de 23 et de 4 avec votre code et décrire ce que vous observez. Modifier la fonction aligner_quartets(q1, q2) pour qu'elle ajoute des quartets '0000' au début du nombre le plus court jusqu'à ce que les deux listes aient la même longueur et effectuer à nouveau des tests.

Appel professeur — Appeler le professeur pour lui présenter votre réponse ou en cas de difficulté.

Fichier fourni : addition_BCD.py

#############################################################################
# Question 1 : Mise en évidence du problème des flottants                   #
#############################################################################
# Écrire ci-dessous la fonction calcul_recettes() et son appel
 
 
#############################################################################
# Question 2 : Conversion BCD vers Décimal                                  #
#############################################################################
# Écrire ci-dessous la fonction convertir_BCD_vers_decimal(liste_quartets)
# et l'assertion de test demandée
 
 
#############################################################################
# Code fourni pour les questions 3 et 4                                     #
#############################################################################
 
def convertir_dec_vers_BCD(decimal):
    """
    Convertit une chaîne représentant un 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] != '.':
            # convertit en binaire le nombre decimal[i]
            # en rajoutant des 0 devant pour obtenir un quartet
            quartet = bin(int(decimal[i]))[2:].zfill(4)
            liste_quartets.append(quartet)
 
        # Si le nombre n'a qu'un seul chiffre après la virgule
        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, quartet2, retenue):
    """
    Additionne bit à bit deux quartets binaires purs.
    Renvoie un tuple (somme_binaire_str, nouvelle_retenue_int).
    """
    somme = ""
    for i in range(4):
        # Lecture de la droite vers la gauche
        bit1 = int(quartet1[3 - i])
        bit2 = int(quartet2[3 - i])
        total = bit1 + bit2 + retenue
 
        if total == 0:
            somme = '0' + somme
            retenue = 0
        elif total == 1:
            somme = '1' + somme
            retenue = 0
        elif total == 2:
            somme = '0' + somme
            retenue = 1
        elif total == 3:
            somme = '1' + somme
            retenue = 1
 
    return somme, retenue
 
 
def corriger_BCD(somme, retenue):
    """
    Applique la correction BCD si le quartet dépasse 9 ou génère une retenue.
    Ajoute '0110' (6) au quartet invalide.
    """
    # Si somme >= 10 ('1010' ou '1011' ou '1100' etc.)
    if somme[0] == '1' and (somme[1] == '1' or somme[2] == '1'):
        somme, retenue = additionner_binaire_quartets(somme, '0110', 0)
        return somme, retenue
 
    # S'il y a eu dépassement naturel lors de l'addition binaire
    if retenue == 1:
        somme, _ = additionner_binaire_quartets(somme, '0110', 0)
        return somme, retenue
 
    return somme, retenue
 
 
def aligner_quartets(q1: list, q2: list) -> tuple:
    """
    Doit équilibrer les deux listes en ajoutant des '0000' à gauche 
    de la liste la plus courte.
    """
    return q1, q2
 
 
def additionner_nombres_format_BCD(a, b):
    """
    Additionne deux nombres au format BCD, quartet par quartet.
    """
    liste_quartets1 = convertir_dec_vers_BCD(a)
    liste_quartets2 = convertir_dec_vers_BCD(b)
 
    # Ajustement de la longueur
    liste_quartets1, liste_quartets2 = aligner_quartets(
        liste_quartets1, liste_quartets2)
 
    retenue = 0
    resultat = []
    longueur_max = max(len(liste_quartets1), len(liste_quartets2))
 
    for i in range(longueur_max):
        index = longueur_max - i - 1
 
        # Addition binaire simple des quartets
        somme, retenue = additionner_binaire_quartets(
            liste_quartets1[index], liste_quartets2[index], retenue)
 
        resultat.insert(0, somme)
 
    # Gestion de la dernière retenue éventuelle
    if retenue == 1:
        resultat.insert(0, '0001')
 
    return resultat

Corrigé

Corrigé réservé aux abonnés Premium.

Créez un compte gratuit : votre première correction est offerte.

Sujet officiel de la banque nationale de sujets 2026 de l'épreuve pratique de NSI (ministère de l'Éducation nationale, sujets.examens-concours.gouv.fr). Corrigé rédigé pour ce site.