Adloun

La dichotomie entière qui ne se termine pas

Exercice · niveau 2 · informatique (MP2I/MPI), chapitre 15 — Diviser pour régner

Énoncé

Le cours avertit que la dichotomie flottante ne peut pas s'arrêter sur une égalité. Sur les entiers, une autre boucle infinie guette. Laquelle ?

Corrigé

Voici la recherche d'un seuil sur les entiers, telle qu'on l'écrit spontanément — étant une propriété monotone, fausse puis vraie :


(* FAUX : ne termine pas. *)
while !bas < !haut do
  let m = (!bas + !haut) / 2 in
  if p m then haut := m else bas := m       (* <-- bas := m *)
done

Mesuré sur dans : la boucle atteint l'état , , et y reste. En effet par troncature, est faux puisque , donc : rien n'a bougé, et le tour suivant est identique. L'exécution a été arrêtée à cent tours.

Le diagnostic. La division entière tronque vers le bas : quand , le milieu vaut . L'affectation bas := m ne change alors rien, et le variant cesse de décroître.

La correction — une unité :


(* Plus petit n de [bas, haut] tel que p n, en supposant p monotone et p haut vrai.
   Complexité : Theta(log (haut - bas)). *)
let cherche_seuil p bas0 haut0 =
  let bas = ref bas0 and haut = ref haut0 in
  (* INVARIANT : le seuil est dans [bas, haut]. *)
  while !bas < !haut do
    let m = !bas + (!haut - !bas) / 2 in
    if p m then haut := m else bas := m + 1        (* +1 : m est ÉLIMINÉ *)
  done;
  !bas

Elle rend en tours, et l'on vérifie .

Le raisonnement qui l'aurait évitée. Écrire le variant avant le code. Le variant est ; pour qu'il décroisse strictement, il faut que chaque branche élimine au moins une valeur. Si est faux, alors n'est pas le seuil : on peut, et l'on doit, l'éliminer — d'où . Si est vrai, est un candidat qu'il faut garder : , et c'est le choix de la troncature vers le bas qui rend cette branche sûre.

La règle générale, et elle se retient. Dans une dichotomie entière, la branche qui garde le candidat doit être celle vers laquelle la division tronque. Ici la troncature va vers le bas, donc c'est haut qui garde. Si l'on cherchait le plus grand tel que , il faudrait arrondir le milieu vers le haut, sans quoi la même boucle infinie reviendrait de l'autre côté.

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.