Math : Ecrire un nombre à virgule sous forme de fraction

Partagez votre expérience de PureBasic avec les autres utilisateurs.
Le Soldat Inconnu
Messages : 4312
Inscription : mer. 28/janv./2004 20:58
Localisation : Clermont ferrand OU Olsztyn
Contact :

Math : Ecrire un nombre à virgule sous forme de fraction

Message par Le Soldat Inconnu »

Salut,

Je viens de mettre au point ce petit algo pour écrire un nombre à virgule sous forme de fraction.

Donc si j'ai le nombre 0.25, l'algo retourne 1/4

Code : Tout sélectionner

Procedure.s Fraction(Valeur.d)
	Protected NewList Reste.q()
	Protected Entier.q, Numerateur.q, Denominateur.q, Reel.d, Signe.q
	
	Reel.d = Abs(Valeur)
	If Reel <> Valeur
		Signe = -1
	Else
		Signe = 1
	EndIf
	Entier = IntQ(ValD(StrD(Reel, 4)))
	; Debug Reel
	; Debug Entier
	While ValD(StrD(Reel, 4)) <> Entier 
		AddElement(Reste())
		Reste() = Entier
		Reel = 1 / (Reel - Entier)
		Entier = IntQ(ValD(StrD(Reel, 4)))
		; Debug Reel
		; Debug Entier
		If ListSize(Reste()) > 32 Or Entier > 10000
			ProcedureReturn ""
		EndIf
	Wend
	
	If ListSize(Reste()) = 0
		ProcedureReturn ""
	EndIf
	
	; Debug ""
	
	Numerateur = Entier
	Denominateur = 1
	; Debug Str(Numerateur) + "/" + Str(Denominateur)
	
	Repeat 
		Swap Numerateur, Denominateur
		Numerateur = Reste() * Denominateur + Numerateur
		; Debug Str(Numerateur) + "/" + Str(Denominateur)
	Until PreviousElement(Reste()) = 0
	
	; Debug ""
	
	If ValD(StrD(Valeur - Signe * Numerateur / Denominateur, 12)) = 0 And Numerateur <= 10000 And Denominateur <= 10000 ; And Str(Denominateur) <> LSet("1", Len(Str(Denominateur)), "0")
		Debug Str(Signe * Numerateur) + "/" + Str(Denominateur)
		ProcedureReturn Str(Signe * Numerateur) + "/" + Str(Denominateur)
	Else
		ProcedureReturn ""
	EndIf
	
EndProcedure

Debug Fraction(0.154)

J'ai fais plusieurs test concluant, dite moi ce que vous en pensez :D

_________________________
Explication de l'algo :
13/9 = 1,444444444
je garde 1
reste 0,4444444444
1/0,444444444 = 2,25
je garde 2
reste 0.25
1/0.25 = 4
je garde 4
reste 0
la fraction s'écrit alors de la forme 1 + 1/(2 + 1/(4))
on simplifie
1 + 1/(8/4 + 1/4)
1 + 1/(9/4)
1 + 4/9
9/9 + 4/9
13/9
Je ne suis pas à moitié Polonais mais ma moitié est polonaise ... Vous avez suivi ?

[Intel quad core Q9400 2.66mhz, ATI 4870, 4Go Ram, XP (x86) / 7 (x64)]
Cls
Messages : 620
Inscription : mer. 22/juin/2005 8:51
Localisation : Nantes

Re: Math : Ecrire un nombre à virgule sous forme de fraction

Message par Cls »

Yeah il est mortel ce code ! :)

Par contre j'ai eu quelques retours négatifs avec des opérations compliquées (plutôt très compliquées même). Sur des choses "simples", ça marche impec' !
Le Soldat Inconnu
Messages : 4312
Inscription : mer. 28/janv./2004 20:58
Localisation : Clermont ferrand OU Olsztyn
Contact :

Re: Math : Ecrire un nombre à virgule sous forme de fraction

Message par Le Soldat Inconnu »

Correction, le code plantait sur un nombre sans virgule :mrgreen:
Je ne suis pas à moitié Polonais mais ma moitié est polonaise ... Vous avez suivi ?

[Intel quad core Q9400 2.66mhz, ATI 4870, 4Go Ram, XP (x86) / 7 (x64)]
Cls
Messages : 620
Inscription : mer. 22/juin/2005 8:51
Localisation : Nantes

Re: Math : Ecrire un nombre à virgule sous forme de fraction

Message par Cls »

Yes exact :)

Pour ce genre de test :

Code : Tout sélectionner

Debug Fraction(0.458167)
Il n'arrive pas à trouver une fraction dû au fait de la virgule flottante et de son approximation de stockage :(
Le Soldat Inconnu
Messages : 4312
Inscription : mer. 28/janv./2004 20:58
Localisation : Clermont ferrand OU Olsztyn
Contact :

Re: Math : Ecrire un nombre à virgule sous forme de fraction

Message par Le Soldat Inconnu »

Tu peux baisser la précision du système pour augmenter les chances de trouver un résultat, mais ça augmente les risques d'erreurs

remplace

Code : Tout sélectionner

ValD(StrD(Reel, 8))
par

Code : Tout sélectionner

ValD(StrD(Reel, 6))
ça vient de me donner une idée, d'ailleurs :)
Je ne suis pas à moitié Polonais mais ma moitié est polonaise ... Vous avez suivi ?

[Intel quad core Q9400 2.66mhz, ATI 4870, 4Go Ram, XP (x86) / 7 (x64)]
Avatar de l’utilisateur
SPH
Messages : 4947
Inscription : mer. 09/nov./2005 9:53

Re: Math : Ecrire un nombre à virgule sous forme de fraction

Message par SPH »

3.1415926000000001
3
7.0625159789423986
7
15.995910436296411
15
1.0041063569117694
1
243.52486193634428
243
1.9052629477479508
1
1.1046514192232537
1
9.5555321411044787
9
1.8000758660189391
1
1.2498814705858512
1
4.0018973702030953
4
527.04527475377347
527
22.08736473760769
22
11.446265706084864
11
2.2408174913844614
2
4.1525222866951781
4
6.5564188792850988
6
1.7972071711240738
1
1.2543790826542431
1
3.9311408373903878
3
1.0739513936501772
1
13.522395598525728
13
1.9142580887399072
1
1.0937830491368887
1
10.662907734428298
10
1.5085055552450526
1
1.9665468541795823
1
1.0346109923960316
1
28.892554959350345
28
1.1203791873251809
1
8.3070838258667976
8
3.2564398244594153
3
3.8995503218271086
3
1.1116665468685114
1
8.9552334879443443
8
1.0468644709598622
1
21.338126293081697
21
2.9574748265979549
2
1.0444138814104837
1
22.515483183236341
22
1.9399274942816416
1
1.0639118507372423
1
15.646550498298856
15
1.546669599097221
1
1.8292584801705016
1
1.2058966219970313
1
4.8568062472361415
4
1.1671250101475898
1
5.9835448872487103
5
1.0167304135933439
1
59.771385472373652
59
1.2963687233088175
1

Il ne retourne pas de fraction = a 3.1415926.....

!i!i!i!i!i!i!i!i!i!
!i!i!i!i!i!i!
!i!i!i!
//// Informations ////
Intel Core i7 4770 64 bits - GTX 650 Ti
Version de PB : 6.12LTS- 64 bits
Cls
Messages : 620
Inscription : mer. 22/juin/2005 8:51
Localisation : Nantes

Re: Math : Ecrire un nombre à virgule sous forme de fraction

Message par Cls »

Yes merci :)
Si le code ne trouve pas de fraction, tu souhaites baisser la précision ?
Le Soldat Inconnu
Messages : 4312
Inscription : mer. 28/janv./2004 20:58
Localisation : Clermont ferrand OU Olsztyn
Contact :

Re: Math : Ecrire un nombre à virgule sous forme de fraction

Message par Le Soldat Inconnu »

mise à jour du code pour plus de précision :)
Je ne suis pas à moitié Polonais mais ma moitié est polonaise ... Vous avez suivi ?

[Intel quad core Q9400 2.66mhz, ATI 4870, 4Go Ram, XP (x86) / 7 (x64)]
Cls
Messages : 620
Inscription : mer. 22/juin/2005 8:51
Localisation : Nantes

Re: Math : Ecrire un nombre à virgule sous forme de fraction

Message par Cls »

J'ai essayé avec

Code : Tout sélectionner

Debug Fraction(0.0054)
Il me dit :
La debuggeur ! a écrit :0.0054000000000000003
0
185.18518518518516
185
5.4000000000006754
5
2.4999999999957789
2
2.0000000000168843
2
59226717877.044922
59226717877
22.260869565217391
22
3.8333333333333424
3
1.1999999999999871
1
5.0000000000003233
5

5/1
6/5
23/6
512/23
30324079553047/512
60648159106606/30324079553047
151620397766259/60648159106606
818750147937901/151620397766259
151620397766277944/818750147937901
818750147937901/151620397766277944

818750147937901/151620397766277944
Alors je le crois mais il y a plus simple : 27/5000
Le Soldat Inconnu
Messages : 4312
Inscription : mer. 28/janv./2004 20:58
Localisation : Clermont ferrand OU Olsztyn
Contact :

Re: Math : Ecrire un nombre à virgule sous forme de fraction

Message par Le Soldat Inconnu »

oui, j'ai réussi à le faire planter également. C'est corrigé
Je ne suis pas à moitié Polonais mais ma moitié est polonaise ... Vous avez suivi ?

[Intel quad core Q9400 2.66mhz, ATI 4870, 4Go Ram, XP (x86) / 7 (x64)]
Cls
Messages : 620
Inscription : mer. 22/juin/2005 8:51
Localisation : Nantes

Re: Math : Ecrire un nombre à virgule sous forme de fraction

Message par Cls »

J'ai un nouveau cas de plantage mais bon c'est vraiment pour t'embêter ! ;)

Code : Tout sélectionner

Debug Fraction(0.999999)
Y'a un moment où on atteint les limites de l'informatique et de la représentation binaire..
En tout cas bravo, ton code est bien sympa !
Avatar de l’utilisateur
SPH
Messages : 4947
Inscription : mer. 09/nov./2005 9:53

Re: Math : Ecrire un nombre à virgule sous forme de fraction

Message par SPH »

1.1205, c'est simplement "1.1205" sans le "." divisé par 10 puissance le nombre de chiffres apres le point. :wink:
1.1205 = 11205/10^4 = 11205/10000
0.0147 = 147/10^4 = 147/10000
0.1 = 1/10^1 = 1/10
127.000 = 127/10^0 = 127/1... et bin ouai, ca fait bien ca
voila le mecanisme... :mrgreen:

!i!i!i!i!i!i!i!i!i!
!i!i!i!i!i!i!
!i!i!i!
//// Informations ////
Intel Core i7 4770 64 bits - GTX 650 Ti
Version de PB : 6.12LTS- 64 bits
Le Soldat Inconnu
Messages : 4312
Inscription : mer. 28/janv./2004 20:58
Localisation : Clermont ferrand OU Olsztyn
Contact :

Re: Math : Ecrire un nombre à virgule sous forme de fraction

Message par Le Soldat Inconnu »

Dernière petite mise à jour du code.

Je l'ai intégré dans ma Calculatrice en cours de réalisation :)
Je ne suis pas à moitié Polonais mais ma moitié est polonaise ... Vous avez suivi ?

[Intel quad core Q9400 2.66mhz, ATI 4870, 4Go Ram, XP (x86) / 7 (x64)]
Le Soldat Inconnu
Messages : 4312
Inscription : mer. 28/janv./2004 20:58
Localisation : Clermont ferrand OU Olsztyn
Contact :

Re: Math : Ecrire un nombre à virgule sous forme de fraction

Message par Le Soldat Inconnu »

J'ai expliqué le principe de l'algo dans le premier post
Je ne suis pas à moitié Polonais mais ma moitié est polonaise ... Vous avez suivi ?

[Intel quad core Q9400 2.66mhz, ATI 4870, 4Go Ram, XP (x86) / 7 (x64)]
Le Soldat Inconnu
Messages : 4312
Inscription : mer. 28/janv./2004 20:58
Localisation : Clermont ferrand OU Olsztyn
Contact :

Re: Math : Ecrire un nombre à virgule sous forme de fraction

Message par Le Soldat Inconnu »

un petit test de rapidité, sur mon PC, je trouve une fraction en 0.16ms environ en moyenne, je trouve que c'est correct :)

Code : Tout sélectionner

Procedure.s Fraction(Valeur.d)
	Protected NewList Reste.q()
	Protected Entier.q, Numerateur.q, Denominateur.q, Reel.d, Signe.q, Precision.l
	
	Precision = 12
	Repeat
		Reel.d = Abs(Valeur)
		If Reel <> Valeur
			Signe = -1
		Else
			Signe = 1
		EndIf
		Entier = IntQ(ValD(StrD(Reel, Precision)))
		; Debug Reel
		; Debug Entier
		While ValD(StrD(Reel, Precision)) <> Entier 
			AddElement(Reste())
			Reste() = Entier
			Reel = 1 / (Reel - Entier)
			Entier = IntQ(ValD(StrD(Reel, Precision)))
			; Debug Reel
			; Debug Entier
			If ListSize(Reste()) > 50 Or Entier > 10000
				ClearList(Reste())
				Break
			EndIf
		Wend
		Precision - 2
	Until Precision < 4 Or ListSize(Reste()) > 0
	
	If ListSize(Reste()) = 0
		ProcedureReturn ""
	EndIf
	
	; Debug ""
	
	Numerateur = Entier
	Denominateur = 1
	; Debug Str(Numerateur) + "/" + Str(Denominateur)
	
	Repeat 
		Swap Numerateur, Denominateur
		Numerateur = Reste() * Denominateur + Numerateur
		; Debug Str(Numerateur) + "/" + Str(Denominateur)
	Until PreviousElement(Reste()) = 0
	
	; Debug ""
	
	If ValD(StrD(Valeur - Signe * Numerateur / Denominateur, 12)) = 0 And Numerateur <= 10000 And Denominateur <= 10000 ; And Str(Denominateur) <> LSet("1", Len(Str(Denominateur)), "0")
		ProcedureReturn Str(Signe * Numerateur) + "/" + Str(Denominateur)
	Else
		ProcedureReturn ""
	EndIf
	
EndProcedure

Max = 5000
Temps1 = ElapsedMilliseconds()
For n = 1 To Max
	Repeat
		Numerateur = Random(9999) + 1
		Denominateur = Random(9999) + 1
	Until Numerateur % Denominateur <> 0 ; Si la division n'est pas entiere
	Reel.d = Numerateur / Denominateur
	Texte.s = Fraction(Reel)
	If Texte <> ""
		Ok + 1
	Else
		Debug Str(Numerateur) + "/" + Str(Denominateur)
	EndIf
Next
Temps2 = ElapsedMilliseconds()

MessageRequester("Fraction", "Détermination bonne : " + Str(Ok) + "/" + Str(Max) + Chr(10) + "Temps d'analyse de " + Str(Max) + " valeurs = " + Str(Temps2 - Temps1) + "ms" + Chr(10) + "Temps d'analyse moyen = " + StrD((Temps2 - Temps1)/Max, 3) + "ms")
Je ne suis pas à moitié Polonais mais ma moitié est polonaise ... Vous avez suivi ?

[Intel quad core Q9400 2.66mhz, ATI 4870, 4Go Ram, XP (x86) / 7 (x64)]
Répondre