[C++] (double) 0==1.3877e-016 (float) 0==7.45058e-008

0==7.45058e-008 [C++] (double) 0==1.3877e-016 (float) - Programmation

Marsh Posté le 23-06-2001 à 18:51:09    

tous est limite dans le titre, pourquoi est-ce que c 2 format ne marche t'il pas comme on s'attend a ce qu'il le fasse, ya t'il une bonne ame pour demistifier ceci pour moi ?
:)

Reply

Marsh Posté le 23-06-2001 à 18:51:09   

Reply

Marsh Posté le 23-06-2001 à 23:56:45    

il y un truc pernitieux avec l'algèbre flottante, c'est que les opérations ne sont pas associatives, et y'a d'autres problèmes.
 
Un flottant (float, double ou long double), c'est un signe, une mantisse, et un exposant.
genre,  
 
0.002567
 
c'est
+      signe
2567   mantisse
-3     exposant
 
la mantisse et l'exposant ont un nombre de chiffres max, et quand tu fais une addition (une soustraction ou une comparaison), et que la différence d'exposant des deux opérandes dépasse la précision de la mantisse, un élément est négligeable devant l'autre.
 
ex imaginons une mantisse à 7 chiffres (ce qui correspond grosso-modo à un float)
 
et que l'on veut faire
 
834.7894
-
0.000001237564
 
c'est donc
8.347894E+3
-
1237564E-6
 
et l'opération se fait dans l'exposant le plus élevé
donc ça donne
8.347894
-
0.000000001237564
 
le tout E+3
 
et comme tout est tronqué à sept chiffre, on a en fait:
8.347894
-
0.000000
 
E+3
=
8.347894E+3
 
donc l'op néglige les chiffres trops loins,
et il faut savoir que 0, c'est
+0.000000E+0
donc les valeurs plus petites en valeur absolue à
1E-7 sont négligeables devant 0 (dans la logique de la virgule flottante), donc si tu considères
0-1.3877E-16, le résultat est 0 donc 0==1.3877€-16
quelle merde non.
 
Donc de manière générale, il faut éviter de faire des == et des != avec des flottants, car les résultats sont souvent imprévisibles à cause des erreurs de précision et d'arrondi.


---------------
-----------------------
Reply

Marsh Posté le 23-06-2001 à 23:59:42    

D'ailleurs, pour les malheureux qui s'amusent à sommer 10000 termes d'une série à terme général décroissant, mieux vaut commencer par la fin pour avoir un meilleur résultat
 
ex
 
float tot=0
for (int i=0; i<1000000; i++)
  tot+=1.0/(i*i);
 
et float tot=0;
 
for (int i=1000000-1; i<=0; i--)
  tot+=1.0/(i*i);
 
ne donnent pas le même résultat pour tot!


---------------
-----------------------
Reply

Marsh Posté le 25-06-2001 à 15:39:55    

merci pour la reponse mais une question ne viens jamais seul :)
comment peut-on faire pour pouvoir travailler avec des nombre reel exact?
et je suppose qu'il y a moyen etant donner qu'il existe des soft de math qui arrive a avoir des reponse exact ou des soft comme excel  
y faut faire koi? ce faire une class qui permettrer la gestion symbolique et faire la simplification qu'a la fin?

Reply

Marsh Posté le 25-06-2001 à 15:45:09    

ben si tu veux un irrationnel "exact", faut passer en symbolique.
Sinon, il existe des libs qui calcules dans une précision quelconque...

Reply

Marsh Posté le 25-06-2001 à 15:48:46    

TukMaster666:
comment peut-on faire pour pouvoir travailler avec des nombre reel exact?

 
Les seuls nombres réels exacts que tu pourras coder seront les rationnels (il faut bien les coder sur un nombre fini de bits)..
 
Pour tt le reste des réels, pas d´espoir sur un ordi sans calcul symbolique (bonjour l´angoisse), Excel & co y sont soumis aussi..
 
Ouf il va falloir que je retourne en prépa moi, ça me semble bien loin tte l´algèbre!! :D


---------------
Athlon64 s754 10*200MHz - R9800Pro - 512MB DDR200MHz - ZX6RR - Q2[SupOp] - Tutorial Video: multilangues, multisstitres
Reply

Marsh Posté le 25-06-2001 à 16:05:33    

Janoscoder > oui c'est meme pire puisque mantisse et exposants sont exprimes en base 2, du coup des nombres decimaux (suite decimale finie) deviennent de simples rationnels :
lesxemple le plus simple etant 1/3 qui en pase dix est 0.333...et en base 3 c'est 0.1 exactement !
essayez d'exprimer 0.2 en base 2 : 0.2 c'est 1/5.. bon courage...
 
TukMaster666 > ce que tu decouvres s'appelle a quelque chose pres la precision machine...
essaies un boucle dans ce genre
double result;
for (result =1; result != (1.0+result) ; result /=2); //le ; est volontaire la boucle est vide...

Reply

Marsh Posté le 25-06-2001 à 16:15:05    

dire qu'on peut représenter les nombres rationnels en virgule flottante est une erreur, comme le dit BENB sans le dire avec l'ex de 1/5.
Mais si tu veux traiter les rationnels de manière bien, y'a un lib de rationnels sur  
http://www.boost.org
 
sinon si tu veux faire des calculs à précision arbitraire, y'a un logiciel qui s'appelle PARI et qui est gratos et qui fait ça très bien. Ca reste de la virgule flottante, mais avec autant de chiffres significatifs que l'on veut.
 
Les irrationnels eux, ne peuvent être représentés que par une formule les calculant, qui peut devenir vite horrible s'ils ne sont pas algébriques. Certains n'ont même pas de formule à écriture finie pouvant les représenter, ni d'écriture finie, mais je ne peux pas te citer d'exemple pour ces deux même raisons.
 
En fait, il faut que sache quel est le problème que tu veux résoudre, et que tu choisisse le type de données représentable en informatique pour le résoudre dans les meilleures conditions, sachant que les type système sont plus rapides.
 
Tiens, si tu nous parlais de ton programme...

 

[edit]--Message édité par janoscoder--[/edit]


---------------
-----------------------
Reply

Marsh Posté le 26-06-2001 à 11:39:40    

c pas pour un programme en particulier c juste que ca me casse les -biip- de pas pouvoir avoir une pressision legitime avec des reel je veut pas que ce soir exact jusqu'a la 972344 decimal apres la virgule je veut juste pouvoir utiliser des reel avec un minimum de pressision (genre 3-4 chiffres)
et personellement je trouve que
 
for(float i=1.0f;i>-1.0f;i-=0.1f)
    cout<<i<<endl;
 
affiche :
1
0.9
0.8
0.7
0.6
0.5
0.4
0.3
0.2
0.0999999
-7.45058e-008
-0.1
-0.2
-0.3
-0.4
-0.5
-0.6
-0.7
-0.8
-0.9
n'est pas genial :(
c quand meme pas des exposant trop elogner 1 et 0.1 :(
qu'il y ai des erreur de pressision je comprend et je c ce que c la pressision machien mais ca c plus de l'erreur c de l'hereie  
on croirer kil on rien fait pour limiter la casse :(
 
j'utilise des float principalement en opengl et g rencontrer par exemple un probleme quand je coder ma console j'avais coder une fonction pour pouvoir gerer la transparance de la concole au choix de l'utilisateur et le truc c que c plus naturel pour kelkun de donner ca valeur en pourcentage mais opengl veut une valeur qui va de 0.0f a 1.0f => " l'algorithme" de passage en pourcentage n'est pas fort compliquer :)  
donc j'avais fait le code suivant l'utilisateur rentre un pourcentage je divise par 100 je stock la valeur puis j'applique la transparence par la ligne de code qui definicer la couleur de la texture de ma console (glColor4f(1.0f1,1.0f,1.0f,blend)
et le truc qui a merder c par exemple quand g mis 70 comme valeur d'entrer il a bien prix 70 blend valer bien 0.7 => pas de prob (g debuger pour verifier )
puis quand je lui demander d'afficher la valeur je faisait 0.7 *100 =70.0
int i=(int)70.0
et ca pour lui ca valler 69
mais 40.0 ca vaut 40 ce traitement etait reserver a 70 pas au autre chiffre FABULEUX :(
donc voila pourqoui je cherche a trouver une solution pour avoir un peu de pressision c pas trop demander que 70.0 en double soit = a 70 en entier (je trouve personnelement :))
maintenant par contre g un nouveau projet vue tous ce que g pu lire comme message je vais faire une class de reel (gerer symboliquement et simplifier le plus possible sans perdre de pressision et la conversion ne ce fait tjs qu'au dernier moment en un chiffre aproximatif voila :) )

Reply

Marsh Posté le 26-06-2001 à 11:54:02    

y'a beaucoup plus simple, tu stockes toujours ton alpha en entier. l'utilisateur édite alors toujours le même int, et à chaque fois qu'il change la transparence, tu fait blendfloat = blendint / 100.

Reply

Marsh Posté le 26-06-2001 à 11:54:02   

Reply

Marsh Posté le 07-05-2006 à 11:10:37    

Bonjours à tous, j'ai un problème moi aussi, j'aissaye de calculer pi, mais quelque soit le type (à part int forcément hein!), j'ai toujours le même résultat même en montant la précision c'est à dire en demandant à la suite de calculer de 0 à 1000 le résultat est le même que si je faisais de 0 à 1. c'est à dire 3.1414. Comment faire pour le forcer à calculer avec une précision plus grande? ça fait un moment que je cherche et je ne trouve pas :'( long double me renvoie la même chose que float, j'ai aissayé d'inclure la biblio Math.h mais rien  n'a changé. Il faut faire quoi pour changer cette précision?? Merci d'avance :hello:


---------------
"C'est vrai qu'un type aussi pénible de jour on serait en droit d'espérer qu'il fasse un break de nuit mais bon …"
Reply

Marsh Posté le 07-05-2006 à 11:12:44    

soit plus explicite !
quelle est ta méthode de calcul ?


---------------
Töp of the plöp
Reply

Marsh Posté le 07-05-2006 à 11:15:07    

_darkalt3_ a écrit :

soit plus explicite !
quelle est ta méthode de calcul ?


 
 
 

Code :
  1. long double Pi(long double n){
  2.  long double pi=0;
  3.  long double p=1;
  4.     for (long double i=0;i<=n;i++)
  5. {
  6.  for (long double k=0;k<i;k++)
  7.  {
  8.   p=p*16;
  9.  }
  10.  pi= pi + ( (1/(p))* ( (4/(8*i+1)) - (2/(8*i+4)) - (1/(8*i+5))- (1/(8*i+6))));
  11.   }
  12. return (pi);
  13. }


 
Pour le p=p*16 c'est car il n'aimait pas le  "^i" avec des float donc je calcule la puissance différemment.


Message édité par burn2 le 07-05-2006 à 11:16:09

---------------
"C'est vrai qu'un type aussi pénible de jour on serait en droit d'espérer qu'il fasse un break de nuit mais bon …"
Reply

Marsh Posté le 07-05-2006 à 11:16:49    

ca vient d'ou ca ?


---------------
Töp of the plöp
Reply

Marsh Posté le 07-05-2006 à 11:18:46    

Comment ça?


---------------
"C'est vrai qu'un type aussi pénible de jour on serait en droit d'espérer qu'il fasse un break de nuit mais bon …"
Reply

Marsh Posté le 07-05-2006 à 11:22:01    

ton algo


---------------
Töp of the plöp
Reply

Marsh Posté le 07-05-2006 à 11:24:44    

Ah ben le calcul marche, j'ai vérifié à la la calculatrice ça vient de ça:
 
http://upload.wikimedia.org/math/f/9/7/f9733b62958be8751fbab97431c27af5.png
 
http://fr.wikipedia.org/wiki/Pi
 
Sur la calculatrice tout est ok, là il faudrait que  je modifie la précision des décimales, il me pond toujours 3.14143 quelque soit le k que je lui lance, on fait comment?


Message édité par burn2 le 07-05-2006 à 11:30:37

---------------
"C'est vrai qu'un type aussi pénible de jour on serait en droit d'espérer qu'il fasse un break de nuit mais bon …"
Reply

Marsh Posté le 07-05-2006 à 11:32:10    

Je me demande si c'est pas la puissance qu'il n'aime pas ...


---------------
"C'est vrai qu'un type aussi pénible de jour on serait en droit d'espérer qu'il fasse un break de nuit mais bon …"
Reply

Marsh Posté le 07-05-2006 à 11:33:18    

Ok c'est bien ça, il n'aime pas le long double p, si je lui met int ça marche mais il devient trop grand pour être codé.
 
J'ai trouvé y a des erreurs dans mon algo, j'initialise jamais p à 1 à chaque passage.


Message édité par burn2 le 07-05-2006 à 11:34:32

---------------
"C'est vrai qu'un type aussi pénible de jour on serait en droit d'espérer qu'il fasse un break de nuit mais bon …"
Reply

Marsh Posté le 07-05-2006 à 11:36:32    

ca sert a rien de mettre des doubles là où tu fais des incréments, comme ton n, ton i et ton k
 
essaie de tracer les resultats pas à pas pour voir ou ca coupe ta précision, parce que double devrait suffire.
 
comment affiche tu ton resultat ?


---------------
Töp of the plöp
Reply

Marsh Posté le 07-05-2006 à 11:37:14    

Bon toujours bloqué now mais à 3.14159 :(


---------------
"C'est vrai qu'un type aussi pénible de jour on serait en droit d'espérer qu'il fasse un break de nuit mais bon …"
Reply

Marsh Posté le 07-05-2006 à 11:37:31    

implémente des traces :o

Message cité 1 fois
Message édité par _darkalt3_ le 07-05-2006 à 11:37:51

---------------
Töp of the plöp
Reply

Marsh Posté le 07-05-2006 à 11:38:28    

_darkalt3_ a écrit :

ca sert a rien de mettre des doubles là où tu fais des incréments, comme ton n, ton i et ton k
 
essaie de tracer les resultats pas à pas pour voir ou ca coupe ta précision, parce que double devrait suffire.
 
comment affiche tu ton resultat ?


je fais un cout<<Pi(x)<<endl;
 
ça vient pas de ça?
Le problème c'est que si je ne met pas de long double double partout la précision diminue encore plus, c'est ce que j'avais fais au début. :/


---------------
"C'est vrai qu'un type aussi pénible de jour on serait en droit d'espérer qu'il fasse un break de nuit mais bon …"
Reply

Marsh Posté le 07-05-2006 à 11:41:44    

_darkalt3_ a écrit :

implémente des traces :o


 
Si je fais ça:
 

Code :
  1. long double Pi(long int n){
  2.  long double pi=0;
  3.  long int p=1;
  4.     for (long int i=0;i<=n;i++)
  5. {
  6.  p=1;
  7.  for (long int k=0;k<i;k++)
  8.  {
  9.   p=p*16;
  10.  }
  11.  cout<<"i : "<<i<<" | p : "<<p<<endl;
  12.  pi= pi + ( (1/(p))* ( (4/(8*i+1)) - (2/(8*i+4)) - (1/(8*i+5))- (1/(8*i+6))));
  13.  //cout<<"pi= "<<pi<<endl;
  14. }
  15. return (pi);
  16. }


 
 
il me met le truc de débugage quand i ateind 8, p passe à 0 donc doit y avoir un blem de taille maximum. :(
 

Citation :


i : 0 | p : 1
i : 1 | p : 16
i : 2 | p : 256
i : 3 | p : 4096
i : 4 | p : 65536
i : 5 | p : 1048576
i : 6 | p : 16777216
i : 7 | p : 268435456
i : 8 | p : 0  -----> Message d'erreur debogage machin truc
 



---------------
"C'est vrai qu'un type aussi pénible de jour on serait en droit d'espérer qu'il fasse un break de nuit mais bon …"
Reply

Marsh Posté le 07-05-2006 à 11:43:06    

Ah oui et si je lance avec un Pi(5) pi=4, donc si je met des int dans les boucle il me pond un int comme résultat d'ou mes long float partout :/


---------------
"C'est vrai qu'un type aussi pénible de jour on serait en droit d'espérer qu'il fasse un break de nuit mais bon …"
Reply

Marsh Posté le 07-05-2006 à 11:56:04    

Bon le mieux que je puisse faire c'est ça:
 

Code :
  1. long double Pi(long int n){
  2.  long double pi=0;
  3.  long double p=1; // si je met un int ça merde, il veut pas passer i=7  
  4.     for (long double i=0;i<=n;i++)
  5. {
  6.  p=1;
  7.  for (long int k=0;k<i;k++)
  8.  {
  9.   p=p*16;
  10.  }
  11.  cout<<"i : "<<i<<" | p : "<<p<<endl;
  12.  pi= pi + ( (1/(p))* ( (4/(8*i+1)) - (2/(8*i+4)) - (1/(8*i+5))- (1/(8*i+6))));
  13.  //cout<<"pi= "<<pi<<endl;
  14. }
  15. return (pi);


 
mais la précision maximum reste 3.14159 pour pi de (15) Je vais tenter un plus grand nombre mais je n'y crois pas :/ Je vois pas pourquoi p qui est un entier  normalement ne passe pas en int mais en float oui. :(
 
 

Citation :


i : 0 | p : 1
i : 1 | p : 16
i : 2 | p : 256
i : 3 | p : 4096
i : 4 | p : 65536
i : 5 | p : 1.04858e+006
i : 6 | p : 1.67772e+007
i : 7 | p : 2.68435e+008
i : 8 | p : 4.29497e+009
i : 9 | p : 6.87195e+010
i : 10 | p : 1.09951e+012
i : 11 | p : 1.75922e+013
i : 12 | p : 2.81475e+014
i : 13 | p : 4.5036e+015
i : 14 | p : 7.20576e+016
i : 15 | p : 1.15292e+018
le resultat de pi est: 3.14159


 
PI(1500)= 3.14159 :( Problème de précision. Comment faire, je sens que je vais passer en String de [1000]


Message édité par burn2 le 07-05-2006 à 12:01:45

---------------
"C'est vrai qu'un type aussi pénible de jour on serait en droit d'espérer qu'il fasse un break de nuit mais bon …"
Reply

Marsh Posté le 07-05-2006 à 12:03:48    

mais non :o
 
fait tes calculs pas à pas, vérifie les retour, affiche les, debug quoi.
 
vérifie un tutoriel aussi sur les cast ou les calculs en C, ca serait peut etre pas superflu.


---------------
Töp of the plöp
Reply

Marsh Posté le 07-05-2006 à 12:08:11    

Je t'ai affiché les calcul pas à pas. Si je déclare p en int il passe pas 16^8 je suppose que c'est le max de nombre entier qui passe et me pond un pi entier, si c'est en float il me pond bien un float mais de max de 3.14159. Tu pourrais me donner des tuto ou autre pour apprendre?


---------------
"C'est vrai qu'un type aussi pénible de jour on serait en droit d'espérer qu'il fasse un break de nuit mais bon …"
Reply

Marsh Posté le 07-05-2006 à 12:09:44    

non t'as imprimé ton p*16
 
t'as pas les soustractions ...
pour les tutos, y'a google ou les bibliolinks


---------------
Töp of the plöp
Reply

Marsh Posté le 07-05-2006 à 12:10:59    

Citation :


i : 0 | p : 1
pi= 3.13333
i : 1 | p : 16
pi= 3.14142
i : 2 | p : 256
pi= 3.14159
i : 3 | p : 4096
pi= 3.14159
i : 4 | p : 65536
pi= 3.14159
i : 5 | p : 1.04858e+006
pi= 3.14159
i : 6 | p : 1.67772e+007
pi= 3.14159
i : 7 | p : 2.68435e+008
pi= 3.14159
i : 8 | p : 4.29497e+009
pi= 3.14159
i : 9 | p : 6.87195e+010
pi= 3.14159
i : 10 | p : 1.09951e+012
pi= 3.14159
i : 11 | p : 1.75922e+013
pi= 3.14159
i : 12 | p : 2.81475e+014
pi= 3.14159
i : 13 | p : 4.5036e+015
pi= 3.14159
i : 14 | p : 7.20576e+016
pi= 3.14159
i : 15 | p : 1.15292e+018
pi= 3.14159
le resultat de pi est: 3.14159


le résultat est toujours le même à partir de Pi(2) :(


---------------
"C'est vrai qu'un type aussi pénible de jour on serait en droit d'espérer qu'il fasse un break de nuit mais bon …"
Reply

Marsh Posté le 07-05-2006 à 12:17:32    

et (4/(8*i+1)) - (2/(8*i+4)) - (1/(8*i+5))- (1/(8*i+6))) ?
 
tu geres pas le resultat ?


---------------
Töp of the plöp
Reply

Marsh Posté le 07-05-2006 à 12:20:14    

le pi affiché avant le dernier "le résultat de pi est: ..." correspond a ce calcul là à chaque boucle ;)


---------------
"C'est vrai qu'un type aussi pénible de jour on serait en droit d'espérer qu'il fasse un break de nuit mais bon …"
Reply

Marsh Posté le 07-05-2006 à 12:23:08    

je crois que tu ne comprends pas ce que je dis.


---------------
Töp of the plöp
Reply

Marsh Posté le 07-05-2006 à 12:24:37    

Non effectivement je ne comprend pas :/ Tu pourrais expliquer mieux stp?


---------------
"C'est vrai qu'un type aussi pénible de jour on serait en droit d'espérer qu'il fasse un break de nuit mais bon …"
Reply

Marsh Posté le 07-05-2006 à 12:32:03    

C'est bon grace à l'aide de fouge et google j'ai trouvé faut que je fasse un printF particulier et ça roule!
 

Code :
  1. printf("%.151le",Pi(n) );

Me permettra d'en afficher 151, reste à pouvoir rendre cette longueur variable.


Message édité par burn2 le 07-05-2006 à 12:36:12

---------------
"C'est vrai qu'un type aussi pénible de jour on serait en droit d'espérer qu'il fasse un break de nuit mais bon …"
Reply

Marsh Posté le 07-05-2006 à 12:42:50    

Bon ben en fait non :'( Toujours bloqué, la limite est maintenant de:
 
3.141592653589793100000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000e+000
 
 
J'ai lancé Pi(15000) pour voir :(


---------------
"C'est vrai qu'un type aussi pénible de jour on serait en droit d'espérer qu'il fasse un break de nuit mais bon …"
Reply

Marsh Posté le 07-05-2006 à 12:57:43    

Toujours bloqué a 17 décimaux maintenant. :(


---------------
"C'est vrai qu'un type aussi pénible de jour on serait en droit d'espérer qu'il fasse un break de nuit mais bon …"
Reply

Marsh Posté le 07-05-2006 à 13:14:26    

Y en a qui ont des idées pour passer cette limite? :(


---------------
"C'est vrai qu'un type aussi pénible de jour on serait en droit d'espérer qu'il fasse un break de nuit mais bon …"
Reply

Marsh Posté le 07-05-2006 à 13:48:40    

burn2 a écrit :

Y en a qui ont des idées pour passer cette limite? :(


 
 
http://fr.wikipedia.org/wiki/Virgu [...] d.27emploi
 
utilises gmp


Message édité par skelter le 07-05-2006 à 13:48:56
Reply

Marsh Posté le 07-05-2006 à 14:42:34    

gmp?

Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed