Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
4750 connectés 

 


Dernière réponse
Sujet : [C] Precision de calcul -- débutant
snotling Ouais j'ai compris en fait :  
 
printf("%.17lg", sin(M_PI));
 
Ca renvoie meme pas 0, donc mes problemes sont tout de suite resolus : ce ne sont plus des problemes, c'est la limite de la becane. :)
 
Merci a tous.
@+.

Votre réponse
Nom d'utilisateur    Pour poster, vous devez être inscrit sur ce forum .... si ce n'est pas le cas, cliquez ici !
Le ton de votre message                        
                       
Votre réponse


[b][i][u][strike][spoiler][fixed][cpp][url][email][img][*]   
 
   [quote]
 

Options

 
Vous avez perdu votre mot de passe ?


Vue Rapide de la discussion
snotling Ouais j'ai compris en fait :  
 
printf("%.17lg", sin(M_PI));
 
Ca renvoie meme pas 0, donc mes problemes sont tout de suite resolus : ce ne sont plus des problemes, c'est la limite de la becane. :)
 
Merci a tous.
@+.
BENB Bon le prog complet pour determiner quel niveau de precision donnent des differents types de donnees du C/C++
 
int main()
{
   float epsm;
   double eps;
   long double eps2;
   for(epsm=1.0F; (1.0F+epsm)!=1.0F; epsm /= 2.0F);
   printf("%g\n",(double)(epsm));
   for(eps=1.0; (1.0+eps)!=1.0; eps /= 2.0);
   printf("%g\n",eps);
   for(eps2 = 1.0L; (1.0L+eps2) != 1.0L; eps2/=2.0L);
   printf("%g\n",(double)(eps2));
}
 
Le cas float est donne a titre d'exemple, puisque normalement les calculs sont fait en double puis tronque.
 
ton prog, je reprends la version qui minimise le nombre d'addtions successives autant de sources de troncatures...
 
 
for ( i = 0; i< n ; i++)  
{  
      long double argument = (long double)(i)*(long double)(M_PI)*2.0L/((long double)(n));
      long double result = (long double)(s)*sinl(argument)+(long double)(d)
      printf("%lg\n",(double)(resultat));  
}  
s,n,d sont des doubles (stockage) mais les calculs sont faits en long double (additions, multiplication, divisions et sinus) donc avec une precision accrue...
le resultat est affiche comme un double, la troncature est fait sur le resultat et non lors de calculs intermediaires...
snotling

BENB a écrit a écrit :

 
Certes l'interface doit etre en double, mais l'implementation, et en particulier les phases de calcul peuvent etre en long double...  




 
Euh on fait ca comment stp ? T'aurais un petit exemple vite fait pour me montrer ?
Merci.

BENB

minusplus a écrit a écrit :

 
bah ça ça te donne la précision en admettant que ton calcul sorte pas des registres du proco, non, tu perds de la précision en passant en 32 bits ?
non ?  




Ben ca depend de la machine, mais sur un PC les registres du proco ils font 80 bits...

minusplus

BENB a écrit a écrit :

for (eps = 1.0; (1.0+eps)!=1.0;eps /= 2); //sisi il y a un ;  a la fin  
 
cette simple ( :D ) ligne te donne la presision machine, c'est a dire la precision a attendre d'une addition.  
voici les valeurs que j'avais obtenu sur je ne sais quelle machine  
double 1.11022e-16  
long double 9.62965e-35  
 
tu as donc 16 chiffres significatif sur une addition de doubles, et 34 sur une addition de long doubles....  
 
A voir sur ta machine... mais de toute evidence pour avoi tes 17 decimales les doubles sont un peu justes...  
 
a voir en long double avec des sinl et cosl mais la ca depend du compilo...  
 
 




bah ça ça te donne la précision en admettant que ton calcul sorte pas des registres du proco, non, tu perds de la précision en passant en 32 bits ?
non ?

BENB

snotling a écrit a écrit :

Salut,
Bah en fait cette precision, je l'ai pas choisi, on ma l'a impose, c'est un programme que j'ai a faire pour mon 'assignment' de ce semestre.
Un extrait :
 

The generator must send a data stream
representing a sequence of sine wave samples to
stdout. Each sample should be should be sent as a
double and followed by a new_line code so that, if
sent to the screen, a single column of numbers is
produced. Samples should have 17 decimal places
of accuracy.
Four parameters are required to specify the number sequence. They are:
n: the number of samples per cycle (an int)
s: the scale factor (a double)
d: The offset (a double)
y: the number of cycles to be sent (a double)
The diagram below shows samples of a sine wave where y=2 cycles, n=16 samples per cycle,
the scale factor s=1 and the offset d=0.5. In this case there are 32 samples generated. The
amplitude of each sample is s * sin(a) + d where a is the angle for the sample. Be aware that
the sin( ) function in math.h expects the angle in radians, not degrees.

 
En totalite si vous voulez :
http://joule.ee.port.ac.uk:5050/assignment_2001.pdf
 
Voili voilo :)
 
@+.  
 
 




Certes l'interface doit etre en double, mais l'implementation, et en particulier les phases de calcul peuvent etre en long double...

snotling Salut,
Bah en fait cette precision, je l'ai pas choisi, on ma l'a impose, c'est un programme que j'ai a faire pour mon 'assignment' de ce semestre.
Un extrait :
 

The generator must send a data stream
representing a sequence of sine wave samples to
stdout. Each sample should be should be sent as a
double and followed by a new_line code so that, if
sent to the screen, a single column of numbers is
produced. Samples should have 17 decimal places
of accuracy.
Four parameters are required to specify the number sequence. They are:
n: the number of samples per cycle (an int)
s: the scale factor (a double)
d: The offset (a double)
y: the number of cycles to be sent (a double)
The diagram below shows samples of a sine wave where y=2 cycles, n=16 samples per cycle,
the scale factor s=1 and the offset d=0.5. In this case there are 32 samples generated. The
amplitude of each sample is s * sin(a) + d where a is the angle for the sample. Be aware that
the sin( ) function in math.h expects the angle in radians, not degrees.

 
En totalite si vous voulez :
http://joule.ee.port.ac.uk:5050/assignment_2001.pdf
 
Voili voilo :)
 
@+.

 

[edtdd]--Message édité par snotling--[/edtdd]

deathsharp arf
avait pas caller que c t une variable :D
BENB

deathsharp a écrit a écrit :

eps est pas definie chez moi...
 
a ne pas oublier non plus le "bug" de tous les processeurs sur les virgules flotants  




ajoute double eps ou long double eps avant :D
et pour faire du long double il faut mettre 1.0L au lieu de 1.0, en particulier lors de la comparaison, et 2.0L au lieu de 2.0 lors de la division...

 

[edtdd]--Message édité par BENB--[/edtdd]

deathsharp eps est pas definie chez moi...
 
a ne pas oublier non plus le "bug" de tous les processeurs sur les virgules flotants
BENB for (eps = 1.0; (1.0+eps)!=1.0;eps /= 2); //sisi il y a un ;  a la fin
 
cette simple ( :D ) ligne te donne la presision machine, c'est a dire la precision a attendre d'une addition.
voici les valeurs que j'avais obtenu sur je ne sais quelle machine
double 1.11022e-16
long double 9.62965e-35
 
tu as donc 16 chiffres significatif sur une addition de doubles, et 34 sur une addition de long doubles....
 
A voir sur ta machine... mais de toute evidence pour avoi tes 17 decimales les doubles sont un peu justes...
 
a voir en long double avec des sinl et cosl mais la ca depend du compilo...

 

[edtdd]--Message édité par BENB--[/edtdd]

youdontcare il n'y a pas vraiment moyen avec les flottants/doubles si tu veux 17 décimales après la virgule. à moins de te faire ta classe de nombre décimal et de calculer le sinus à coups de développements limités, tu n'auras jamais la précision que tu veux.
 
des libs doivent exister pour ça, chercher avec www.google.com
 
pourquoi as-tu besoin d'autant de précision au fait ?
snotling Alors personne a une idee pour resoudre mon probleme ? ;-)
snotling Merci flo850, mais apparemment ca veux pas marcher ;-) J'ai toujours les meme imprecisions, et comme j'ai besoin de 17 decimales pres la virgule..... Jusqu'a 14 ca va (bien qu'il y ait un petit 1.224606...e-16 d'ou je ne sais ou) mais au dela les resultats sont pas les bons.
 
D'ailleurs, j'ai essaye avec M_PIl au lieu de M_PI et j'ai un beau 'variable non definie' alors qu'elle est bien dans mon math.h. Peut etre est ce que ca va vient du #ifdef __USE_BSD au lieu de #ifdef __USE_GNU ? Ca veut dire quoi ca ?
deathsharp moi g M_PI et M_PI2 (pi/2), M_PI4
pas de PI ni de M_PIl
flo850 mes excuses , je savais pas .
mais pour le reste , je crois que mon explicataion tient debout
verdoux J'ai M_PI et M_PIl (en long double) dans math.h
flo850 en C , tu ne travaille qu'avec des intervalles ( 1/9 ne peux pas etre codé exactement en binaire )
tu fasi a chaque fois un double (+imprecision) + un autre double( avec lui aussi une erreur ), donc a chaque tour de boucle , ton erreur augmente , ce qui peux donner des resultats abberrants .
enfin ca c mon explication.
pour arranger essaye ca :
for ( i = 0; i< n ; i++)
{
       printf("%lg\n",sin(i*M_PI*2/n));
}
en plus , ca allège ton code ( moi j'aime pas les for qui font une ligne )
 au fait , pi est defini en tant que PI dans math.h ( donc pourkoi M_PI)
snotling Salut,
Voila un petit prog de de debutant en C, ce que je comprends pas c'est pourquoi les valeurs ne tombent pas juste.
Le programme sert juste a calculer des sinus et ce un certain nb de fois par periode, etc, enfin un truc basique quoi.
 
 
#include <stdio.h>
#include <math.h>
 
int main()
{
 
int n=8;
double s=1, d=0, y=1, a; // g besoin que ce soit des 'double', c impose, les autres variables sont la pour le nb de periodes, un decalage...
 
for (a=0; a<y*2*M_PI; a=a+M_PI*2/n)
{
 printf("%.20lg\t%.20lg\n", a, s*sin(a)+d);
}
 
}
 
 
Et la sortie du programme, ca donne :
 
0 0
0.785398163397448279 0.70710678118654746172
1.570796326794896558 1
2.356194490192344837 0.70710678118654757274
3.141592653589793116 1.2246063538223772582e-16
3.926990816987241395 -0.70710678118654746172
4.712388980384689674 -1
5.497787143782137953 -0.70710678118654768376
 
Et donc la question est de savoir d'ou viennent toutes ces imprecisions.
 
Merci.

Copyright © 1997-2025 Groupe LDLC (Signaler un contenu illicite / Données personnelles)