Cette page présente un listing détaillé et commenté de l'implémentation de l'algorithme d'Euclide en JavaScript.
Pour commencer, nous avons besoin d'un formulaire: deux zones de texte (a et b) pour entrer le paramètres, une troisième pour afficher le résultat, et un bouton pour lancer le calcul.
<form>
|
calcul(form)
:
C'est la fonction principale du programme.Tout d'abord, elle appelle la fonction
check(form)
, qui vérifie que la saisie est correcte, c'est-à-dire que les cases a et b contiennent bien des nombres entiers. Dans le cas contraire, le script s'arrête en affichant un message d'alerte.Si la fonction
check(form)
ne décèle pas d'erreur, le script continue.Tout d'abord, on teste si l'un au moins des entiers a et b est nul (c'est la condition
eval(a*b)==0
). Si c'est le cas, le script retourne la plus grande des valeurs absolues de a et b (car PGCD(a,0)=|a| pour tout entier a).
Sinon, on utilise l'algorithme d'Euclide proprement dit.L'algorithme utilise le lemme suivant:
Lemme :
Si a, b, q et r sont des entiers relatifs tels que a=bq+r, alors PGCD(a,b)=PGCD(b,r).On effectue donc la division euclidienne de a par b. On obtient ainsi un quotient q et un reste r. Il nous faut donc deux variables globales q et r pour cette division:
Si r est nul, alors PGCD(a,b)=PGCD(b,0)=|b|. Sinon, on effectue une nouvelle division euclidienne de b par r; comme on a |r|<|b|, on obtiendra un reste nul en au plus |b| étapes. Le dernier reste non nul (notons-le rn) vérifie PGCD(a,b)=PGCD(rn,0)=|rn|; la fonction doit donc retourner sa valeur absolue.
var q=0, r=0;
NB: Ici, la fonction de
divise(a,b)
ne retourne que des restes positifs; on pourrait donc envisager une fonctioncalcul(form)
qui renverrait le dernier reste non nul, et non sa valeur absolue. Toutefois, cette valeur absolue s'avère nécéssaire dans le cas particulier où b est négatif et divise a; dans ce cas, en effet, la fonctiondivise(a,b)
ne fait rien d'autre que retourner q=a/b et r=0, et donc le dernier reste non nul est b, et pas |b|.
function calcul(form) {
if (check(form)) { //verifie la saisie
var a=form.a.value; //passage des parametres
var b=form.b.value;
if (eval(a*b)==0) { //cas particulier: PGCD(a,0)=|a|
form.resultat.value=max(abs(eval(a)),abs(eval(b)));
}
else {
for (;abs(eval(b))>0;) { //l'algo lui-meme
divise(eval(a),eval(b)); //si a=bq+r avec r<b alors
a=b; //PGCD(a,b)=PGCD(b,r)
b=r; //on continue jusqu'a r=0
} //PGCD(a,b) est le dernier r non nul
}
form.resultat.value=abs(a); //renvoie le resultat
}
else {
alert("Attention! vous devez entrer des entiers!");
}
}
- La fonction divise(a,b)
:
Cette fonction n'est pas optimisée, mais elle a le mérite d'être simple.Le quotient q est initialisé à 0. La variable i indique le signe de q (positif si a et b sont de même signe, négatif sinon). La division ne pose aucun problème ici, car cette fonction n'est appelée par la fonction
calcul(form)
que si a et b sont tous deux non nuls.
La fonction se contente d'ajouter i à q et de soustraire ib à r jusqu'à obtenir un reste r compris dans l'intervalle [0,|b|[. Notons que l'on conserve toujours l'égalité a=bq+r.La théorie générale nous assure de l'existence d'un couple (q,r) vérifiant a=bq+r et 0
r<|b|. Or si q est non nul, si a et bq étaient de signes opposés, alors on aurait |r|=|a-bq|=|a|+|b||q|
|b|; donc a et bq sont de même signe, donc q est du signe du produit ab, ce qui justifie la valeur de la variable i et nous assure de trouver un couple (q,r) convenable.
function divise(a,b) { //Division euclidienne
//renvoie q et r avec a=bq+r et 0<=r<|b|
q=0; //initialisation
var i=(a*b)/abs(a*b);
for (r=a;(r>=abs(b))||(r<0);r-=(i*b)) {
q+=i;
}
}
- Le fonctions max(a,b)
et abs(a)
:
Pas grand chose à en dire;max(a,b)
retourne le plus grand des deux paramètres etabs(a)
retourne la valeur absolue de a.
function max(a,b) { //explicite...
if (a>=b) { return(a) }
else { return(b) }
}
function abs(a) { //valeur absolue
return max(a,-a);
}
- Le fonctions de vérification de saisie :
La fonctionisDigit(c)
vérifie que son argument, un caractère, est bien un chiffre.La fonction
isInteger(s)
vérifie que la chaîne de caractères passée en argument est bien un entier: le premier caractère peut être un chiffre ou un signe + ou -; les autres, s'ils existent, doivent être des chiffres.La fonction
check(form)
vérifie que les champs de saisie a et b contiennent bien des entiers.
function isDigit(c) { //verifie que c contient un chiffre
var test=""+c;
if (test=="0"||test=="1"||test=="2"||test=="3"||test=="4"||test=="5"||test=="6"||
test=="7"||test=="8"||test=="9") {
return true;
}
return false;
}
function isInteger(s) { //verifie que s contient un entier
var test=""+s;
for (var k=1;k<test.length;k++) { //verifie que tous les caracteres sauf le premier
//sont des chiffres
var c=test.substring(k,k+1);
if (isDigit(c)==false) {
return false;
}
}
return (isDigit(test.substring(0,1))||test.substring(0,1)=="+"||test.substring(0,1)=="-");
//le premier caractere peut etre + ou -
//ou un chiffre
}
function check(form) { //verification de la saisie
return (isInteger(form.a.value)&&isInteger(form.b.value));
}
<script language="JavaScript">
|