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

  FORUM HardWare.fr
  Programmation

  [C] Precision de calcul -- débutant

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

[C] Precision de calcul -- débutant

n°77394
snotling
Posté le 02-12-2001 à 04:09:39  profilanswer
 

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.

mood
Publicité
Posté le 02-12-2001 à 04:09:39  profilanswer
 

n°77404
flo850
moi je
Posté le 02-12-2001 à 12:06:53  profilanswer
 

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)


---------------

n°77405
verdoux
And I'm still waiting
Posté le 02-12-2001 à 12:09:00  profilanswer
 

J'ai M_PI et M_PIl (en long double) dans math.h

n°77407
flo850
moi je
Posté le 02-12-2001 à 12:11:23  profilanswer
 

mes excuses , je savais pas .
mais pour le reste , je crois que mon explicataion tient debout


---------------

n°77408
deathsharp
Posté le 02-12-2001 à 12:13:13  profilanswer
 

moi g M_PI et M_PI2 (pi/2), M_PI4
pas de PI ni de M_PIl


---------------
What butter and whiskey won't cure, there is no cure for.
n°77466
snotling
Posté le 02-12-2001 à 15:16:22  profilanswer
 

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 ?

n°77648
snotling
Posté le 03-12-2001 à 13:56:31  profilanswer
 

Alors personne a une idee pour resoudre mon probleme ? ;-)

n°77653
youdontcar​e
Posté le 03-12-2001 à 14:10:43  profilanswer
 

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 ?

n°77656
BENB
100% Lux.
Posté le 03-12-2001 à 14:19:32  profilanswer
 

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]

n°77671
deathsharp
Posté le 03-12-2001 à 15:03:10  profilanswer
 

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


---------------
What butter and whiskey won't cure, there is no cure for.
mood
Publicité
Posté le 03-12-2001 à 15:03:10  profilanswer
 

n°77673
BENB
100% Lux.
Posté le 03-12-2001 à 15:06:42  profilanswer
 

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]

n°77678
deathsharp
Posté le 03-12-2001 à 15:36:14  profilanswer
 

arf
avait pas caller que c t une variable :D


---------------
What butter and whiskey won't cure, there is no cure for.
n°77753
snotling
Posté le 03-12-2001 à 19:09:28  profilanswer
 

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]

n°77921
BENB
100% Lux.
Posté le 04-12-2001 à 10:50:02  profilanswer
 

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

n°77971
minusplus
Posté le 04-12-2001 à 11:41:34  profilanswer
 

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 ?

n°77989
BENB
100% Lux.
Posté le 04-12-2001 à 11:54:06  profilanswer
 

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

n°77998
snotling
Posté le 04-12-2001 à 12:29:20  profilanswer
 

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.

n°78047
BENB
100% Lux.
Posté le 04-12-2001 à 13:58:02  profilanswer
 

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

n°78635
snotling
Posté le 05-12-2001 à 20:07:15  profilanswer
 

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


Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation

  [C] Precision de calcul -- débutant

 

Sujets relatifs
[Perl] DébutantComment conseilleriez vous un debutant ?
requete SQL : utilisation SUM et traduction en calcul domaineune question de debutant
Calcul de PIProbleme VB : debutant
faire un calcul en aspCalcul de la hauteur
debutant vb 6, besoin d aide, URGENT...[C/C++][Débutant] Bloc conditionnel If
Plus de sujets relatifs à : [C] Precision de calcul -- débutant


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR