Précédent   Forum du club des développeurs et IT Pro > Autres langages > Langages fonctionnels > Caml
Caml Forum d'entraide sur la programmation avec les langages fonctionnels Caml-Light et OCaml
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse
 
Outils de la discussion
Publicité
'
Vieux 17/12/2012, 17h59   #1
AlexiZ
Invité de passage
 
Inscription : décembre 2012
Messages : 7
Détails du profil
Informations forums :
Inscription : décembre 2012
Messages : 7
Points : 1
Points : 1
Par défaut Utiliser le type Num

Bonjour,

Voilà j'ai un petit souci avec ce type de données (plus d'info ici : http://caml.inria.fr/pub/docs/manual...ibref/Num.html), j'aimerais simplement faire une division de 2 entiers et en sortir un nombre décimal très grand.
Mon exemple : 103993 / 33102, qui doit donner une approximation de pi.
En caml, ça me donne ça :
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#load "nums.cma";;
open Num;;

(*Version 1 :*)
Int 103993 // Int 33102;;
(*Résultat*)
- : Num.num = Ratio <abstr>

(*Version 2 :*)
let printnum n = print_string (string_of_num n);;
#install_printer printnum;;
let n = Int 103993 // Int 33102;;
printnum n;;
(*Résultat*)
103993/33102- : unit = ()
Si je remplace mon "//" par une addition (+/), une multiplication (*/) ou une soustraction (-/), j'ai un résultat qui s'affiche correctement et tout va bien dans les 2 cas.
Mais pour la division, rien à faire.
Quelqu'un a une solution pour ma simple division ?
AlexiZ est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 18/12/2012, 16h26   #2
SpiceGuid
Rédacteur
 
Avatar de SpiceGuid
 
Homme Damien Guichard
Inscription : juin 2007
Messages : 1 512
Détails du profil
Informations personnelles :
Nom : Homme Damien Guichard
Localisation : France, Loire (Rhône Alpes)

Informations forums :
Inscription : juin 2007
Messages : 1 512
Points : 2 495
Points : 2 495
Citation:
Envoyé par AlexiZ
j'aimerais simplement faire une division de 2 entiers et en sortir un nombre décimal très grand.
Le résultat de Num.(//) est un nombre rationnel c'est-à-dire ∈ ℚ.

Si tu veux calculer dans ℕ il faut utiliser le module Big_int.

PI en goutte-à-goutte (exact, temps ∞) :

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#load "nums.cma";;
let add  = Big_int.add_big_int
and sub  = Big_int.sub_big_int
and succ = Big_int.succ_big_int
and pred = Big_int.pred_big_int
and mult = Big_int.mult_big_int
and div  = Big_int.div_big_int
and add_int  = Big_int.add_int_big_int
and mult_int = Big_int.mult_int_big_int
and big_int  = Big_int.big_int_of_int
and int_of   = Big_int.int_of_big_int
;;
let pi () =
  let rec g q r t i =
    let i3 = mult_int 3 i in
    let u = mult_int 3 (mult (add_int 1 i3) (add_int 2 i3))
    and y = int_of (div (add (mult q (add_int (-12) (mult_int 27 i))) (mult_int 5 r)) (mult_int 5 t)) 
    in begin
      print_int y;
      flush stdout;
      g
      (mult_int 10 (mult q (mult i (add_int (-1) (mult_int 2 i)))))
      (mult_int 10 (mult u (sub (add (mult q (add_int (-2) (mult_int 5 i))) r) (mult_int y t))))
      (mult t u)
      (add_int 1 i);
      ()
    end
  in g (big_int 1) (big_int 180) (big_int 60) (big_int 2);; 

pi ();;
__________________
Du même auteur: le cours OCaml, le dernier article publié, le projet, le blog dvp et le jeu vidéo.
Avant de poser une question je lis les règles du forum.
SpiceGuid est actuellement connecté   Envoyer un message privé Réponse avec citation 10
Vieux 18/12/2012, 16h53   #3
AlexiZ
Invité de passage
 
Inscription : décembre 2012
Messages : 7
Détails du profil
Informations forums :
Inscription : décembre 2012
Messages : 7
Points : 1
Points : 1
Merci d'avoir répondu.

L'objectif n'est pas de cacluler dans ℕ mais bien dans ℚ. Est-ce que c'est possible ?
La méthode du goutte à goutte donne bien un nombre important de décimales mais je ne comprends pas vraiment comment cela fonctionne, une précision sur les paramètres de g ?
AlexiZ est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 18/12/2012, 17h20   #4
SpiceGuid
Rédacteur
 
Avatar de SpiceGuid
 
Homme Damien Guichard
Inscription : juin 2007
Messages : 1 512
Détails du profil
Informations personnelles :
Nom : Homme Damien Guichard
Localisation : France, Loire (Rhône Alpes)

Informations forums :
Inscription : juin 2007
Messages : 1 512
Points : 2 495
Points : 2 495
Citation:
Envoyé par AlexiZ Voir le message
L'objectif n'est pas de cacluler dans ℕ mais bien dans ℚ. Est-ce que c'est possible ?
Oui, c'est possible en utilisant le module Num.

Citation:
Envoyé par AlexiZ Voir le message
une précision sur les paramètres de g ?
http://web.comlab.ox.ac.uk/oucl/work...ons/spigot.pdf
__________________
Du même auteur: le cours OCaml, le dernier article publié, le projet, le blog dvp et le jeu vidéo.
Avant de poser une question je lis les règles du forum.
SpiceGuid est actuellement connecté   Envoyer un message privé Réponse avec citation 00
Vieux 18/12/2012, 17h28   #5
AlexiZ
Invité de passage
 
Inscription : décembre 2012
Messages : 7
Détails du profil
Informations forums :
Inscription : décembre 2012
Messages : 7
Points : 1
Points : 1
Citation:
Envoyé par SpiceGuid Voir le message
Oui, c'est possible en utilisant Num.(//)
ça va pas être simple
Mais en tout cas merci, je vais voir avec tout ça pour trouver quelque chose de probant.
Juste une dernière question en passant, je ne peux pas utiliser "power_num" sans avoir une "Exception : invalid argument power_num", une idée ?
AlexiZ est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 18/12/2012, 17h49   #6
SpiceGuid
Rédacteur
 
Avatar de SpiceGuid
 
Homme Damien Guichard
Inscription : juin 2007
Messages : 1 512
Détails du profil
Informations personnelles :
Nom : Homme Damien Guichard
Localisation : France, Loire (Rhône Alpes)

Informations forums :
Inscription : juin 2007
Messages : 1 512
Points : 2 495
Points : 2 495
Citation:
Envoyé par AlexiZ Voir le message
L'objectif n'est pas de cacluler dans ℕ mais bien dans ℚ. Est-ce que c'est possible ?
Ne reviens pas demain pour nous dire qu'en fait tu veux calculer ∏ dans ℝ
__________________
Du même auteur: le cours OCaml, le dernier article publié, le projet, le blog dvp et le jeu vidéo.
Avant de poser une question je lis les règles du forum.
SpiceGuid est actuellement connecté   Envoyer un message privé Réponse avec citation 00
Vieux 18/12/2012, 17h54   #7
AlexiZ
Invité de passage
 
Inscription : décembre 2012
Messages : 7
Détails du profil
Informations forums :
Inscription : décembre 2012
Messages : 7
Points : 1
Points : 1
Citation:
Envoyé par SpiceGuid Voir le message
Ne reviens pas demain pour nous dire qu'en fait tu veux calculer ∏ dans ℝ
Parce que ça change quelque chose à mon problème ?
Ne rentrons pas dans les détails mathématiques je ne suis qu'informaticien ^^

Rien pour mon power sinon ? Je suis en train de la redéfinir, pas d'autre choix pour l'instant.
AlexiZ est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 20/12/2012, 19h22   #8
prgasp77
Membre Expert
 
Avatar de prgasp77
 
Homme Yankel Scialom
Ingénieur en systèmes embarqués
Inscription : juin 2004
Messages : 998
Détails du profil
Informations personnelles :
Nom : Homme Yankel Scialom
Âge : 26
Localisation : France, Eure (Haute Normandie)

Informations professionnelles :
Activité : Ingénieur en systèmes embarqués
Secteur : High Tech - Électronique et micro-électronique

Informations forums :
Inscription : juin 2004
Messages : 998
Points : 1 418
Points : 1 418
Bonjour, Num.approx_num_exp n'est-il pas ce qu'il te faut ?

Et je pense qu'il veut calculer dans .
__________________
gasp in touch
-- Yankel Scialom
prgasp77 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 20/12/2012, 19h30   #9
prgasp77
Membre Expert
 
Avatar de prgasp77
 
Homme Yankel Scialom
Ingénieur en systèmes embarqués
Inscription : juin 2004
Messages : 998
Détails du profil
Informations personnelles :
Nom : Homme Yankel Scialom
Âge : 26
Localisation : France, Eure (Haute Normandie)

Informations professionnelles :
Activité : Ingénieur en systèmes embarqués
Secteur : High Tech - Électronique et micro-électronique

Informations forums :
Inscription : juin 2004
Messages : 998
Points : 1 418
Points : 1 418
Ha ! Et pour power :
Code :
1
2
3
# Num.string_of_num (Num.power_num (Num.Int 504) (Num.Int 378)) ;;
- : string =
"33017392796145806168337542681632713604222995935988104123216879182928287894637048840597359552449336745902720910544576973376130276949945491709905194218388383927856494067568803810302723077080946938739059037654665557394630501724251429824678985000638923778108694450062077564482084416549777079249340604967521869646485255276241847131673592534722055015732764520610641645335086861421489622712513199518845994268387656780995195534217937542957200585918221068910253052292848581363845925365716402627687039286067310038747591656793390292631073518412591070311243669118312872835834456483469330329157209133904610082236915275558489487488920630490252596041569445152487024145367571764359878632171319807038019819019452538149624144276074228441991563894798422713706949206950320068915073838271807637016504830677150339287105118769260883601878681028320754504596371742050877247059336773795088839280844064430752831753633722391538027607060217484414866980566718815985992891941408840128305692064276730398785102427676911360823387330617292042046112777895936"
__________________
gasp in touch
-- Yankel Scialom
prgasp77 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 22/12/2012, 13h57   #10
AlexiZ
Invité de passage
 
Inscription : décembre 2012
Messages : 7
Détails du profil
Informations forums :
Inscription : décembre 2012
Messages : 7
Points : 1
Points : 1
Ah une réponse !

Citation:
Envoyé par prgasp77 Voir le message
Bonjour, Num.approx_num_exp n'est-il pas ce qu'il te faut ?
Oui, c'est une réponse alternative à ma première question, mais le vrai problème vient de la fonction "power_num" que je dois utiliser sur des nombres non entiers (et accessoirement positifs) mais qui n'est pas prévue pour ça.
y'a t-il une solution pour pallier à ce problème ?
AlexiZ est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 22/12/2012, 18h03   #11
prgasp77
Membre Expert
 
Avatar de prgasp77
 
Homme Yankel Scialom
Ingénieur en systèmes embarqués
Inscription : juin 2004
Messages : 998
Détails du profil
Informations personnelles :
Nom : Homme Yankel Scialom
Âge : 26
Localisation : France, Eure (Haute Normandie)

Informations professionnelles :
Activité : Ingénieur en systèmes embarqués
Secteur : High Tech - Électronique et micro-électronique

Informations forums :
Inscription : juin 2004
Messages : 998
Points : 1 418
Points : 1 418
Citation:
Envoyé par AlexiZ Voir le message
mais le vrai problème vient de la fonction "power_num" que je dois utiliser sur des nombres non entiers (et accessoirement positifs) mais qui n'est pas prévue pour ça.
y'a t-il une solution pour pallier à ce problème ?
« Ha ! Une question ! » ais-je envie de dire. IL n'a jamais été question d'utiliser Num.power_num sur des rationnels avant ce message.

Est-il possible de ruser ? Num.power_num accepte comme premier argument un ratio, mais requiert un entier en second argument. Sachant que :

il est possible de contourner la limitation ... mais ... mais ... Num ne propose pas d'outil de calcul de racines. Il n'est donc pas adapté à tes besoins.

Il va donc te falloir créer tes propres outils, mais ceux-ci dépendent de tes besoins. Peut être est-il temps pour toi de nous en dire un peu plus .
__________________
gasp in touch
-- Yankel Scialom
prgasp77 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 22/12/2012, 18h13   #12
AlexiZ
Invité de passage
 
Inscription : décembre 2012
Messages : 7
Détails du profil
Informations forums :
Inscription : décembre 2012
Messages : 7
Points : 1
Points : 1
Citation:
Envoyé par prgasp77 Voir le message
« Ha ! Une question ! »
Oui j'avais quelque peu abandonné le sujet sans réponse

Comme dit dans un précédent message, l'idée est de calculer pi en utilisant la librairie Num. Or, dans mes différents algorithmes de calcul de pi (imposés malheureusement) j'utilise 6 fois sur 8 la fonction puissance ou la fonction racine.
Et ces puissances / racines utilisent des décimaux...

Comme "power_num" est ainsi :
Code :
1
2
3
4
let power_num a b = match (a,b) with
  (n, (Int i)) -> power_num_int n i
| (n, (Big_int bi)) -> power_num_big_int n bi
| _ -> invalid_arg "power_num"
c'est-à-dire sans décimaux, donc j'essaye de trouver une alternative. J'ai bien essayé la formule de Newton mais sans succès.

Voilà je crois que j'ai exposé le problème un peu plus clairement.

Donc l'objectif : transformer ma puissance décimale en autre chose de faisable pour un Num.
AlexiZ est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 22/12/2012, 19h30   #13
prgasp77
Membre Expert
 
Avatar de prgasp77
 
Homme Yankel Scialom
Ingénieur en systèmes embarqués
Inscription : juin 2004
Messages : 998
Détails du profil
Informations personnelles :
Nom : Homme Yankel Scialom
Âge : 26
Localisation : France, Eure (Haute Normandie)

Informations professionnelles :
Activité : Ingénieur en systèmes embarqués
Secteur : High Tech - Électronique et micro-électronique

Informations forums :
Inscription : juin 2004
Messages : 998
Points : 1 418
Points : 1 418
Voici une implémentation de la méthode de Newton qui utilise Num. Mais c'est pas utilisable, je te dit pas le temps qu'il faut pour calculer la racine 4ième de 25 .
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
(* Compilation
	ocamlopt -o root nums.cmxa root_num.ml
*)

let root_num index radicand =
	(* parameters *)
	let max_iter = 1000000
	and epsilon = Num.div_num (Num.Int 1) (Num.Int 1000000) in
	(* constants *)
	let one = Num.Int 1 in
	let one_on_index = Num.div_num one index
	and pred_index = Num.sub_num index one
	in
	(* Newton's methode *)
	let rec aux iter acc index radicand =
		if iter <= 0
		then acc
		else begin
			(* New estimation *)
			let new_acc =
				Num.mult_num
					one_on_index
					(Num.add_num
						(Num.mult_num pred_index acc)
						(Num.div_num radicand
							(Num.power_num acc pred_index)
						)
					)
			in
			(* check step *)
			let step = Num.abs_num (Num.sub_num acc new_acc) in
			if Num.le_num step epsilon
			then new_acc
			else aux (pred iter) new_acc index radicand
		end
	in
	aux max_iter one index radicand


(* help message *)
let usage () =
	Printf.printf "%s index radicand\n Compute the index-th root of radicand and print the result in standart output.\n" Sys.executable_name


(* main *)
let main () =
	if Array.length Sys.argv != 3
	then usage ()
	else
		let index = int_of_string Sys.argv.(1)
		and radicand = int_of_string Sys.argv.(2)
		in
		let result =
			Num.approx_num_exp 10
				(root_num (Num.Int index) (Num.Int radicand))
		in
		Printf.printf "%s\n" result


let _ = main ()
__________________
gasp in touch
-- Yankel Scialom
prgasp77 est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 22/12/2012, 20h12   #14
AlexiZ
Invité de passage
 
Inscription : décembre 2012
Messages : 7
Détails du profil
Informations forums :
Inscription : décembre 2012
Messages : 7
Points : 1
Points : 1
Citation:
Envoyé par prgasp77 Voir le message
Voici une implémentation de la méthode de Newton qui utilise Num. Mais c'est pas utilisable, je te dit pas le temps qu'il faut pour calculer la racine 4ième de 25 .
Effectivement, une simple racine cubique de 125 met plusieurs minutes
Mais ça fonctionne ! Tu viens de résoudre mon problème en un seul post, bravo !

Merci beaucoup !
AlexiZ est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Cette discussion est résolue.
Outils de la discussion

Navigation rapide


Fuseau horaire GMT +2. Il est actuellement 20h23.


 
 
 
 
Partenaires

Hébergement Web