0==7.45058e-008 [C++] (double) 0==1.3877e-016 (float) - Programmation
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.
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!
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?
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...
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!!
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...
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]
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 )
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.
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
Marsh Posté le 07-05-2006 à 11:12:44
ReplyMarsh Posté le 07-05-2006 à 11:15:07
_darkalt3_ a écrit : soit plus explicite ! |
Code :
|
Pour le p=p*16 c'est car il n'aimait pas le "^i" avec des float donc je calcule la puissance différemment.
Marsh Posté le 07-05-2006 à 11:18:46
Comment ça?
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://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?
Marsh Posté le 07-05-2006 à 11:32:10
Je me demande si c'est pas la puissance qu'il n'aime pas ...
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.
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 ?
Marsh Posté le 07-05-2006 à 11:37:14
Bon toujours bloqué now mais à 3.14159
Marsh Posté le 07-05-2006 à 11:37:31
implémente des traces
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 |
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.
Marsh Posté le 07-05-2006 à 11:41:44
_darkalt3_ a écrit : implémente des traces |
Si je fais ça:
Code :
|
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 : |
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
Marsh Posté le 07-05-2006 à 11:56:04
Bon le mieux que je puisse faire c'est ça:
Code :
|
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 : |
PI(1500)= 3.14159 Problème de précision. Comment faire, je sens que je vais passer en String de [1000]
Marsh Posté le 07-05-2006 à 12:03:48
mais non
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.
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?
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
Marsh Posté le 07-05-2006 à 12:10:59
Citation : |
le résultat est toujours le même à partir de Pi(2)
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 ?
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
Marsh Posté le 07-05-2006 à 12:23:08
ReplyMarsh Posté le 07-05-2006 à 12:24:37
Non effectivement je ne comprend pas Tu pourrais expliquer mieux stp?
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 :
|
Me permettra d'en afficher 151, reste à pouvoir rendre cette longueur variable.
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
Marsh Posté le 07-05-2006 à 12:57:43
Toujours bloqué a 17 décimaux maintenant.
Marsh Posté le 07-05-2006 à 13:14:26
Y en a qui ont des idées pour passer cette limite?
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
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 ?