Épreuve pratique · 2026 · Sujet 20

Bac NSI pratique 2026 sujet 20 : Usages numériques, émissions et pourcentages d’écart

L’application estime une empreinte mensuelle à partir de quantités d’activités numériques. On utilise exclusivement les coefficients du sujet, exprimés en gCO₂e par unité : ce sont les paramètres de ce modèle pédagogique, pas une estimation actualisée universelle des usages. Les dictionnaires d’utilisateurs peuvent omettre des activités ; les comparaisons considèrent alors une quantité nulle.

Dans ce sujet

Un corrigé pédagogique pour comprendre et justifier vos réponses. Les conseils de rédaction ne constituent pas un barème officiel détaillé.

Application

Usages numériques, émissions et pourcentages d’écart

L’application estime une empreinte mensuelle à partir de quantités d’activités numériques. On utilise exclusivement les coefficients du sujet, exprimés en gCO₂e par unité : ce sont les paramètres de ce modèle pédagogique, pas une estimation actualisée universelle des usages. Les dictionnaires d’utilisateurs peuvent omettre des activités ; les comparaisons considèrent alors une quantité nulle.

ActivitéCoefficient du sujetQuantité utilisateur 1Émission (gCO₂e)
emails_simples4 par email150600
emails_pj19 par email20380
streaming_sd36 par heure10360
streaming_hd100 par heure252500
recherches7 par recherche5003500
stockage_cloud10 parGo et par mois15150

Le dossier comporte le sujet et les fichiers listés dans les téléchargements. Les codes de départ sont reproduits ci-dessous. Travaillez sur une copie. Les appels professeur signalés dans les questions servent à présenter votre démarche ; vous pouvez aussi demander de l’aide en cas de difficulté.

Code fourni : code_empreinte.py
# Données d'émissions en gCO2e par unité
EMISSIONS = {
    'emails_simples': 4,       # par email
    'emails_pj': 19,           # par email avec pièce jointe
    'streaming_sd': 36,        # par heure
    'streaming_hd': 100,       # par heure
    'recherches': 7,           # par recherche
    'stockage_cloud': 10       # par Go par mois
}

# Exemples d'utilisateurs pour les tests
utilisateur1 = {
    'emails_simples': 150,
    'emails_pj': 20,
    'streaming_sd': 10,
    'streaming_hd': 25,
    'recherches': 500,
    'stockage_cloud': 15
}

utilisateur2 = {
    'streaming_hd': 15,
    'emails_simples': 100,
    'recherches': 10
}

utilisateur3 = {
    'emails_simples': 50,
    'emails_pj': 5,
    'streaming_sd': 30,
    'streaming_hd': 5,
    'recherches': 200,
    'stockage_cloud': 5
}

utilisateur4 = {
    'emails_simples': 100,
    'recherches': 50
}

utilisateur5 = {
    'emails_simples': 50,
    'recherches': 100
}

utilisateur6 = {}

#############################################################################
# Écrire le code de la fonction calculer_empreinte de la question 1         #
#############################################################################


#############################################################################
# Écrire le code de la fonction classer_par_impact de la question 2         #
#############################################################################


#############################################################################
# Fonction fournie pour la question 3                                       #
#############################################################################

def comparer(u1, u2):
    """Compare les émissions de deux utilisateurs pour toutes les activités.
    Renvoie un dictionnaire avec, pour chaque activité, la différence des
    émissions (émissions de l’utilisateur 2 moins celles de l’utilisateur 1).
    Si une activité est absente chez un utilisateur, on considère que
    son émission vaut 0."""
    differences = {}
    for activite in EMISSIONS:
        quantite1 = 0
        quantite2 = 0
        if activite in u1:
            quantite1 = u1[activite]
        if activite in u2:
            quantite2 = u2[activite]
        emission1 = quantite1 * EMISSIONS[activite]
        emission2 = quantite2 * EMISSIONS[activite]
        differences[activite] = emission2 - emission1
    return differences


def test_comparer():
    diff = comparer(utilisateur4, utilisateur5)
    assert diff['emails_simples'] == -200  # (50-100) * 4
    assert diff['recherches'] == 350     # (100-50) * 7
    # Ajouter vos tests ci-dessous avec justifications


#############################################################################
# Fonction fournie pour la question 4                                       #
#############################################################################
def comparer_v2(u1, u2):
    """Compare les émissions de deux utilisateurs pour toutes les activités.
    Renvoie un dictionnaire avec, pour chaque activité, l'écart des émissions
    sous forme de pourcentage, en proportion de la première émission."""
    ecarts = {}
    for activite in EMISSIONS:
        quantite1 = 0
        quantite2 = 0
        if activite in u1:
            quantite1 = u1[activite]
        if activite in u2:
            quantite2 = u2[activite]
        emission1 = quantite1 * EMISSIONS[activite]
        emission2 = quantite2 * EMISSIONS[activite]
        ecarts[activite] = (emission2 - emission1)/emission1 * 100
    return ecarts

Question 1

#

Écrire calculer_empreinte(utilisateur) : renvoyer l’empreinte mensuelle totale entière en gCO₂e. utilisateur 1 doit donner 7490.

Indice

La quantité seule n’est pas une émission.

Comprendre la correction
def calculer_empreinte(utilisateur):
    total = 0
    for activite, quantite in utilisateur.items():
        total += quantite * EMISSIONS[activite]
    return total

Chaque quantité est multipliée par le coefficient correspondant, puis les contributions s’additionnent. Les données du sujet utilisent des quantités et coefficients entiers, donc le résultat reste entier sans conversion artificielle. Le total de l’utilisateur 1 est 600+380+360+2500+3500+150=7490 gCO₂e. Une activité absente ne contribue pas ; un dictionnaire vide produit 0.

assert calculer_empreinte(utilisateur1) == 7490
assert calculer_empreinte({}) == 0
assert calculer_empreinte({'streaming_hd': 2}) == 200
Voir la question dans le sujet PDF, p. 2 (nouvel onglet)

Question 2

#

Écrire classer_par_impact : renvoyer trois clés fort, moyen, faible associées aux noms d’activités. Fort si émission≥1000 ; moyen si 200≤émission<1000 ; faible si émission<200. Pour utilisateur 2, attendre fort:[streaming_hd], moyen:[emails_simples], faible:[recherches].

PythonClasser une activité selon son émission réelleÉcrivez votre solution et mettez-la à l’épreuve

Écrivez classer_par_impact(utilisateur). Multipliez la quantité de chaque activité présente par son coefficient dans EMISSIONS, fourni. Classez son nom dans fort pour au moins 1000 gCO₂e, moyen entre 200 inclus et 1000 exclu, faible sous 200. Les trois clés doivent toujours exister avec des listes indépendantes. N’ajoutez pas les activités absentes de l’utilisateur.

def classer_par_impact(utilisateur):
    # À vous de jouer
    pass

Les cas de test proposés :

  • Utilisateur 2 du sujet : Les émissions valent 1500, 400 et 70, et non les seules quantités.
  • Exactement 200 : 200 appartient à la catégorie moyenne.
  • Exactement 1000 : 1000 appartient à la catégorie forte.
  • Juste en dessous des seuils : 49 × 4 = 196 reste faible ; 99 × 10 = 990 reste moyen.
  • Une quantité nulle mais présente : Une activité présente à zéro se classe faible, sans ajouter toutes les activités absentes.
  • Listes indépendantes pour un utilisateur vide : Créer les trois clés avec une même liste partagerait les ajouts entre catégories.
Indice

Multiplier avant de comparer aux seuils.

Comprendre la correction
def classer_par_impact(utilisateur):
    classes = {'fort': [], 'moyen': [], 'faible': []}
    for activite, quantite in utilisateur.items():
        emission = quantite * EMISSIONS[activite]
        if emission >= 1000:
            classes['fort'].append(activite)
        elif emission >= 200:
            classes['moyen'].append(activite)
        else:
            classes['faible'].append(activite)
    return classes

On classe les activités présentes chez l’utilisateur, comme le montre l’exemple. Parcourir toutes les clés de EMISSIONS ajouterait des activités absentes à la catégorie faible et ne correspondrait plus au résultat demandé. Les trois listes doivent être créées séparément. Tester d’abord le seuil le plus élevé permet au elif d’exprimer l’intervalle 200 à 999 sans répéter sa borne supérieure.

assert classer_par_impact(utilisateur2) == {
    'fort':['streaming_hd'],'moyen':['emails_simples'],'faible':['recherches']}
assert classer_par_impact({'streaming_hd':2})['moyen'] == ['streaming_hd']
assert classer_par_impact({'streaming_hd':10})['fort'] == ['streaming_hd']
Voir la question dans le sujet PDF, p. 3 (nouvel onglet)

Question 3

#

Compléter test_comparer avec au moins deux tests pertinents et leur justification. comparer renvoie, pour chaque activité, émission 2−émission 1, avec zéro pour une activité absente.

Comprendre la correction
# Identité : aucune activité ne doit varier.
assert all(v == 0 for v in comparer(utilisateur1,utilisateur1).values())
# Absence chez le premier utilisateur : hausse positive.
assert comparer({}, {'emails_simples':3})['emails_simples'] == 12
# Absence chez le second : disparition, donc différence négative.
assert comparer({'emails_simples':3}, {})['emails_simples'] == -12
# Aucune donnée : les six clés existent, chacune à zéro.
assert comparer({}, {}) == {activite:0 for activite in EMISSIONS}

Ces tests vérifient plusieurs aspects distincts : signe, valeurs par défaut, identité et structure du dictionnaire. Le test initial utilisateur 4 vers utilisateur 5 donne déjà−200 pour les emails et 350 pour les recherches. Une différence positive représente une hausse chez le second utilisateur, pas une économie.

Voir la question dans le sujet PDF, p. 3 (nouvel onglet)

Question 4

#

Identifier les cas qui font échouer comparer_v 2, où le pourcentage est(émission 2−émission 1)/émission 1×100, et corriger.

Indice

Chercher quand le dénominateur devient nul.

Comprendre la correction

Une activité absente ou de quantité nulle chez le premier utilisateur donne une émission de référence nulle. La division provoque ZeroDivisionError, y compris lorsque les deux émissions sont nulles. Le pourcentage relatif à zéro n’est pas défini : aucune valeur numérique universelle ne peut le remplacer. Nous choisissons explicitement None pour ces cas, afin de ne pas inventer 0% ou 100%.

def comparer_v2(u1, u2):
    ecarts = {}
    for activite in EMISSIONS:
        emission1 = u1.get(activite, 0) * EMISSIONS[activite]
        emission2 = u2.get(activite, 0) * EMISSIONS[activite]
        if emission1 == 0:
            ecarts[activite] = None
        else:
            ecarts[activite] = (emission2 - emission1) / emission1 * 100
    return ecarts
assert comparer_v2({}, {'emails_simples':3})['emails_simples'] is None
assert comparer_v2({}, {})['emails_simples'] is None
assert comparer_v2({'emails_simples':3}, {})['emails_simples'] == -100.0
assert comparer_v2({'emails_simples':2},{'emails_simples':3})['emails_simples'] == 50.0

Pour une référence non nulle, la formule est inchangée. utilisateur 1 vers utilisateur 2 donne notamment−40% pour le streamingHD et−98% pour les recherches. Un affichage peut traduire None par « référence nulle, pourcentage non défini » et afficher en complément la différence absolue fournie par comparer. Cette convention est un choix documenté de la correction, car le sujet ne fixe pas de valeur de remplacement.

Le dénominateur fixe le point de vue. Passer de 100 à 150 représente +50%, mais revenir de 150 à 100 représente environ −33,33%, car la référence a changé. Les pourcentages ne sont donc pas simplement opposés lorsque l’on échange les utilisateurs, contrairement aux différences absolues. Tester les deux sens aide à vérifier que le programme divise par l’émission du premier utilisateur. Lorsque cette émission est nulle, ce raisonnement n’a plus de base numérique : afficher la différence absolue accompagne utilement la mention de pourcentage indéfini.

Lire un pourcentage sans lui inventer de valeurUn atelier pour expérimenter

Choisissez une réponse puis confrontez votre intuition à l’explication. Vous pouvez modifier vos choix.

Lire les réponses et leurs explications
  1. Passer de 0 à 12 gCO₂e correspond à…

    Un pourcentage relatif non défini.. La variation absolue est 12, mais pas le pourcentage.

  2. Passer de 12 à 0 gCO₂e correspond à…

    −100%.. La référence 12 est non nulle : (0−12)/12=−1.

Appuyez votre explication sur les valeurs et les conditions exactes du programme.

Voir la question dans le sujet PDF, p. 4 (nouvel onglet)
Variation absolue et relative des emailsUn atelier pour expérimenter

Modifiez les quantités mensuelles d’emails simples. Le coefficient reste 4 gCO₂e par email, comme dans le sujet. Explorez surtout une quantité initiale nulle.

Lire le résultat de l’expérience initiale

Variation absolue : 200gCO₂e ; relative : 50.00%.

Le pourcentage divise par la première émission. Le coefficient commun se simplifie lorsque cette référence est non nulle.

UtilisateurQuantitéÉmission
1100400
2150600

Un nombre manquant parce que la formule est indéfinie est plus honnête qu’un pourcentage inventé.

Revoir les notions de cet exercice

Du sujet à la méthode

Votre prochaine séance de révision

  • Définir l’unité avant de totaliser ou classer.
  • Conserver une différence absolue lorsque la variation relative est indéfinie.

Retrouver ces notions dans d’autres sujets

Toutes les annales de NSI · Le guide pour préparer le bac NSI 2027

Énoncé : sujet 26_BCG_NSI_20 (PDF). Corrigé et explications pédagogiques proposés par Sofien.