J’ai régulièrement un problème avec le fonctionnement des modulos en JavaScript : les modulos de nombres négatifs renvoient un résultat négatif.
3 % 26; // ✔ 3
29 % 26; // ✔ 3
-23 % 26; // ⨯ -23 instead of 3
-49 % 26; // ⨯ -23 instead of 3
-75 % 26; // ⨯ -23 instead of 3
Cela n’est pas forcément un problème. Ici, j’essaie de décoder des messages encodés avec un chiffre Vigenere et quand je décale une lettre « A » (1 dans l’ordre de l’alphabet) de « -1 », je dois obtenir la lettre « Z » (26 dans l’ordre de l’alphabet).
Le fonctionnement des modulos en JavaScript peut être une source régulière de bug, car on ne pense pas forcément à tester notre code avec des nombres négatifs. En plus, un·e développeur·se qui n’est pas habitué·e à JavaScript peut être surpris·e par cette subtilité qui n’existe pas dans tous les autres langages de programmation.
Voici ma solution :
/**
* Returns the remainder of the division
*
* @param {number} number
* @param {number} divisor
* @return {number} the remainder
*/
function positiveModulo(number, divisor) {
return ((number % divisor) + divisor) % divisor;
}
L’astuce ici est de faire un premier modulo pour s’assurer d’avoir une valeur entre « -divisor » et « divisor ». Puis, on ajouter une fois le divisor pour obtenir une valeur entre « 0 » et « 2*divisor », donc forcément positive. Enfin, on réalise le modulo voulu.
positiveModulo(3, 26); // ✔ 3
positiveModulo(29, 26); // ✔ 3
positiveModulo(-23, 26); // ✔ 3
positiveModulo(-49, 26); // ✔ 3
positiveModulo(-75, 26); // ✔ 3
console.log(-23 % 26);
console.log(positiveModulo(-23, 26));