(* calcul_pi.ml : programme de calcul du nombre pien multiprécision, à l'aide de la formule de Machin. Tiré d'un exercice du livre "Mathématiques et informatique" de J. Berstel, JE Pin et M. Pocchiola. *) (* Nombre de chiffres par case : 3 *) let base = 1000;; (* Nombre de cases : 500 *) let taille = 500;; (* D'où 3 * 499 = 1497 chiffres après la virgule, dont la plupart doivent être exacts *) (* somme : n1 >= 0, n2 >= 0 *) let nombre_plus_nombre n1 n2 = let retenue = ref 0 and res = make_vect (taille + 1) 0 in for i = taille downto 0 do let somme = n1.(i) + n2.(i) + !retenue in if somme < base then begin res.(i) <- somme; retenue := 0 end else begin res.(i) <- somme - base; retenue := 1 end done; res;; (* différence : n1 >= n2 >= 0 *) let nombre_moins_nombre n1 n2 = let retenue = ref 0 and res = make_vect (taille + 1) 0 in for i = taille downto 0 do let difference = n1.(i) - n2.(i) - !retenue in if difference >= 0 then begin res.(i) <- difference; retenue := 0 end else begin res.(i) <- difference + base; retenue := 1 end done; res;; (* Conversion d'un entier en nombre *) let nombre_d_entier n = let res = make_vect (taille + 1) 0 in res.(0) <- n; res;; (* produit d'un nombre par un entier *) let nombre_par_chiffre n c = let retenue = ref 0 and res = make_vect (taille + 1) 0 in for i = taille downto 0 do let produit = n.(i) * c + !retenue in res.(i) <- produit mod base; retenue := produit / base done; res;; (* quotient d'un nombre par un entier *) let nombre_sur_chiffre n c = let retenue = ref 0 and res = make_vect (taille + 1) 0 in for i = 0 to taille do let quotient = n.(i) + base * !retenue in res.(i) <- quotient / c; retenue := quotient mod c done; res;; (* Calcul de l'arctangente de l'inverse d'un entier *) let atan_un_sur_chiffre chiffre iterations = let res = ref (make_vect (taille + 1) 0) in for k = iterations downto 1 do res := nombre_moins_nombre (nombre_d_entier 1) !res; res := nombre_par_chiffre !res (2 * k - 1); res := nombre_sur_chiffre !res (2 * k + 1); res := nombre_sur_chiffre !res chiffre; res := nombre_sur_chiffre !res chiffre done; res := nombre_moins_nombre (nombre_d_entier 1) !res; res := nombre_sur_chiffre !res chiffre; !res;; (* Impression d'un nombre *) let print_chiffre c = let largeur_chiffre = function | 0 -> 1 | ch -> 1 + int_of_float (log10 (float_of_int ch)) in let nbre_zero = int_of_float (log10 (float_of_int base)) - (largeur_chiffre c) in print_string " "; print_string (make_string nbre_zero `0`); print_int c;; let print_nombre n = print_int n.(0); print_string ","; let ligne = ref 0 in for i = 1 to taille do print_chiffre n.(i); ligne := (!ligne + 1) mod 10; if !ligne = 0 then begin print_newline (); print_string (make_string 2 ` `) end done; print_newline ();; let calcul_pi = let taille = float_of_int taille and base = float_of_int base in let it1 = 1 + int_of_float ((taille *. log base /. log 5. -. 3.) /. 2.) and it2 = 1 + int_of_float ((taille *. log base /. log 239. -. 3.) /. 2.) in print_nombre (nombre_moins_nombre (nombre_par_chiffre (atan_un_sur_chiffre 5 it1) 16) (nombre_par_chiffre (atan_un_sur_chiffre 239 it2) 4));;