Adloun

Le modulo qui déborde

Exercice · niveau 2 · informatique (MP2I/MPI), chapitre 18 — Algorithmique des textes

Énoncé

Dans le hachage roulant, on doit rendre positive la quantité avant de multiplier par . On hésite entre deux écritures :


/* (A) */ ht = ((ht - t[i] * puissance % Q + Q)     * B + t[i + m]) % Q;
/* (B) */ ht = ((ht - t[i] * puissance % Q + Q * Q) * B + t[i + m]) % Q;

Avec Q = 1000000007 et des long long, laquelle est correcte ? Vérifier.

Corrigé

(A) est correcte, (B) déborde — et le débordement est silencieux.

L'analyse. La quantité ht - t[i] * puissance % Q vit dans : ht est un reste modulo , donc dans , et l'on en retranche un autre reste. Ajouter une fois suffit donc à la rendre positive, et le résultat reste . La multiplication par donne au plus , très en deçà de .

Ajouter « pour être sûr » détruit tout : le produit par vaudrait alors environ , soit vingt-huit fois la capacité d'un long long.

Mesure. Le programme compilé avec gcc -fsanitize=undefined donne :


runtime error: signed integer overflow:
    1000000014000000049 * 256 cannot be represented in type 'long long'

recherche de "abra" dans "abracadabra abracadabra" :
   version (B) : 0
   version (A) : 0 7 12 19

La version (B) ne trouve qu'une occurrence sur quatre. Le débordement corrompt l'empreinte roulante dès la première fenêtre, et toutes les suivantes sont fausses : l'algorithme cesse silencieusement de trouver quoi que ce soit. Sur avec le motif , il rend la position au lieu des positions attendues.

Trois leçons.

Une dernière précaution, indépendante : t[i] est un char, dont le signe n'est pas fixé par la norme. Sur un texte accentué, il peut être négatif, et l'empreinte devient négative. On écrit donc (unsigned char) t[i] partout, comme le fait déjà la table de Boyer-Moore.

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.