Adloun

On dispose de nb bits (chapitre 1) et l'on propose une seconde…

Exercice d'entraînement · niveau 3 (difficile) · NSI (première), chapitre 3 — Langages et programmation · Mettre au point : choisir les cas qui séparent

Énoncé

On dispose de nb_bits (chapitre 1) et l'on propose une seconde implémentation, math.floor(math.log2(n)) + 1. Mettre en place un test différentiel sur à . Que se passe-t-il pour ? Qu'en conclure sur cette manière de tester ?

Corrigé


import math

def nb_bits_formule(n):
    if n == 0:
        return 1
    return math.floor(math.log2(n)) + 1

desaccords = [n for n in range(0, 100000) if nb_bits(n) != nb_bits_formule(n)]
print(len(desaccords))            # 0

Aucun désaccord sur valeurs. La conclusion tentante — « les deux fonctions sont correctes » — est fausse.

Le cas .


gros = 2**60
print(nb_bits(gros), nb_bits_formule(gros))          # 61 61
print(nb_bits(gros - 1), nb_bits_formule(gros - 1))  # 60 61

Sur , les deux fonctions divergent : contre . C'est la version par boucle qui a raison — s'écrit avec soixante bits à . La formule échoue parce que math.log2 convertit son argument en flottant : n'est pas représentable exactement en double précision, il est arrondi à , dont le logarithme vaut exactement (chapitre 2).

Les deux leçons.

La règle qui en découle : le domaine de test doit être choisi d'après les frontières du problème (ici : la limite d'exactitude des flottants, ), et non d'après ce qui s'exécute vite.

Les autres exercices de ce chapitre Le cours du chapitre

Un blocage sur cet exercice ? Le tuteur d'Adloun guide par questions, sans donner la réponse.