Page 1 sur 2
Math : Ecrire un nombre à virgule sous forme de fraction
Publié : jeu. 29/avr./2010 14:38
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
_________________________
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
Re: Math : Ecrire un nombre à virgule sous forme de fraction
Publié : jeu. 29/avr./2010 14:56
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' !
Re: Math : Ecrire un nombre à virgule sous forme de fraction
Publié : jeu. 29/avr./2010 15:03
par Le Soldat Inconnu
Correction, le code plantait sur un nombre sans virgule

Re: Math : Ecrire un nombre à virgule sous forme de fraction
Publié : jeu. 29/avr./2010 15:07
par Cls
Yes exact
Pour ce genre de test :
Il n'arrive pas à trouver une fraction dû au fait de la virgule flottante et de son approximation de stockage

Re: Math : Ecrire un nombre à virgule sous forme de fraction
Publié : jeu. 29/avr./2010 15:10
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
par
ça vient de me donner une idée, d'ailleurs

Re: Math : Ecrire un nombre à virgule sous forme de fraction
Publié : jeu. 29/avr./2010 15:14
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.....
Re: Math : Ecrire un nombre à virgule sous forme de fraction
Publié : jeu. 29/avr./2010 15:23
par Cls
Yes merci

Si le code ne trouve pas de fraction, tu souhaites baisser la précision ?
Re: Math : Ecrire un nombre à virgule sous forme de fraction
Publié : jeu. 29/avr./2010 15:24
par Le Soldat Inconnu
mise à jour du code pour plus de précision

Re: Math : Ecrire un nombre à virgule sous forme de fraction
Publié : jeu. 29/avr./2010 15:29
par Cls
J'ai essayé avec
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
Re: Math : Ecrire un nombre à virgule sous forme de fraction
Publié : jeu. 29/avr./2010 15:42
par Le Soldat Inconnu
oui, j'ai réussi à le faire planter également. C'est corrigé
Re: Math : Ecrire un nombre à virgule sous forme de fraction
Publié : jeu. 29/avr./2010 15:46
par Cls
J'ai un nouveau cas de plantage mais bon c'est vraiment pour t'embêter !
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 !
Re: Math : Ecrire un nombre à virgule sous forme de fraction
Publié : jeu. 29/avr./2010 17:07
par SPH
1.1205, c'est simplement "1.1205" sans le "." divisé par 10 puissance le nombre de chiffres apres le point.

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...

Re: Math : Ecrire un nombre à virgule sous forme de fraction
Publié : jeu. 29/avr./2010 19:44
par Le Soldat Inconnu
Dernière petite mise à jour du code.
Je l'ai intégré dans ma Calculatrice en cours de réalisation

Re: Math : Ecrire un nombre à virgule sous forme de fraction
Publié : jeu. 29/avr./2010 22:25
par Le Soldat Inconnu
J'ai expliqué le principe de l'algo dans le premier post
Re: Math : Ecrire un nombre à virgule sous forme de fraction
Publié : sam. 01/mai/2010 22:23
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")