1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| let division_euclidien_Z a b =
let signe = ref 1 and nb_de_fois = ref 1 and A = ref a and B = ref b and R = ref 1 in
if(!B<0) then failwith "Diviseur négatif"
if(!A<0) then
begin
!A := (-1)*!A;
signe := ref -1;
end;
while (!nb_de_fois * !b < !A || !nb_de_fois * !b = !A) do incr nb_de_fois; done;
!nb_de_fois := (nb_de_fois -1)*!signe;
!R := !A - (!nb_de_fois * !b);
print_string "La division euclidien de ";
printf_int !A;
print_string "par ";
print_int !B*!signe;
print_string " :";
print_newline;
print_string "Quotient : " print_int !nb_de_fois;
print_newline;
print_string "Reste : " print_int !R;
;; |
Plusieurs choses (syntaxiquement parlant). Les majuscules en début de nom de variable sont réservées :
- Aux modules
- Aux constructeurs de types algébriques (type t = A | B)
Vous ne pouvez donc pas écrire
let A = ref a and B = ref b and R = ref 1
mais
let a = ref a and b = ref b and r = ref 1
De plus, si vous écrivez
if e1 then i1 if e2 then i2;
(i1 et i2 étant des instructions (type de retour, unit)) alors il ne faut surtout pas oublier d'ajouter un point-virgule après i1 :
if e1 then i1; if e2 then i2;
Ici, je pense que vous vous êtes un peu emmêlé les pinceaux, il faut écrire idem pour
!nb_de_fois := (nb_de_fois * !b)
qui devient
nb_de_fois := !nb_de_fois * !b
et pour
!r := !a - (!nb_de_fois * !b);
qui devient
r := !a - (!nb_de_fois * !b);
(l'opération r := e signifie que la référence r pointe dorénavant sur le contenu e, c'est donc la référence qu'il faut mettre à gauche de l'opérateur et non pas son contenu, donc r et pas !r)
Dans le même ordre d'idée, devient car à droite de l'opérateur on doit retrouver le contenu (ici, -1) et non pas la référence (ici ref -1).
Ici, plusieurs erreurs. A l'analyse lexicale, *! pourrait être un opérateur donc OCaml va le lire comme tel et vous dire qu'il ne connaît pas l'opérateur *!. Il faut donc mettre une séparation entre les deux. De plus, les opérateurs écrits de la sorte sont infixes, c'est à dire qu'on évalue ce qu'il y a à gauche de l'opérateur puis ce qu'il y a à droite puis on applique l'opérateur entre les deux évaluations, donc votre code va être interprété comme ceci
(print_int !b) *! (!signe)
et ça va râler. Il faut donc écrire est une fonction, si vous ne lui donnez pas d'argument elle ne va rien faire (c'est ce qu'on appelle une application partielle). Il faut donc écrire Enfin,
print_string "Quotient : " print_int !nb_de_fois;
Vous avez oublié le point-virgule entre les deux applications. Il faut donc écrire
print_string "Quotient : "; print_int !nb_de_fois;
Idem pour
print_string "Reste : " print_int !r;
qui devient
print_string "Reste : "; print_int !r;
Et votre code devient donc (même si je ne comprends pas pourquoi vous multipliez !b par !signe et pas !a vu que !signe vient de !a) :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| let division_euclidien_Z a b =
let signe = ref 1 and nb_de_fois = ref 1 and a = ref a and b = ref b and r = ref 1 in
if(!b<0) then failwith "Diviseur négatif";
if(!a<0) then
begin
a := (-1) * !a;
signe := -1;
end;
while (!nb_de_fois * !b < !a || !nb_de_fois * !b = !a) do incr nb_de_fois; done;
nb_de_fois := (!nb_de_fois -1) * !signe;
r := !a - (!nb_de_fois * !b);
print_string "La division euclidien de ";
print_int !a;
print_string "par ";
print_int (!b * !signe);
print_string " :";
print_newline;
print_string "Quotient : "; print_int !nb_de_fois;
print_newline ();
print_string "Reste : "; print_int !r;
;; |
MAIS... C'EST DEGUEU !
Vous êtes en train d'apprendre OCaml et j'en suis très heureux. Je ne fais pas partie des personnes qui crachent sur les aspects impératifs d'OCaml mais vous avez dû vous en rendre compte, c'est un langage fonctionnel a priori. Votre code ne prend en compte rien de tout ça. Je me suis donc permis d'écrire votre code d'une facon bien plus concise et fonctionnelle :
1 2 3 4 5 6 7 8 9 10 11
| let div_eucl a b =
let signe, ua = if a < 0 then -1, -a else 1, a in
if b < 0 then failwith "Diviseur négatif";
let rec dr ai q =
let ai' = ai + b in
if ai' > ua then (q, ua - ai)
else dr ai' (q+1)
in
let (q, r) = dr 0 0 in
let q = signe * q in
Printf.printf "%d = %d * %d + %d\n" a b q r |
Partager