Aide - Recherche - Membres - Calendrier
Version complète : [Aide] Programme C++ [Aide]
iClan, le clan Mac > Détente > Le fumoir
Darknight670
Bonjour,

je débute vraiment en programmation C++ donc je crée des petits programmes pour m'entraîner. Or j'essaye de calculer Pi a l'aide la méthode Monte Carlo (pour maîtriser les rand () ) et mon programme ne marche pas ... mais sans erreurs apparentes de compilation...

CODE
##include <iostream>
#include <stdlib.h>
#include <time.h>
#include <math.h>
#include <iomanip>

using namespace std ;

int main ()
{
cout << "Simulation de Pi\n" ;
cout << "Entrez un nombre etier de simulations a effectuer.\n" ;

int N ;
cin >> N ;

double X ;
double Y ;
double R ;
int M ;
int S ;

srand ( time (0) ) ;


while ( S < N )
{
X = 2 * rand () - 1 ;
Y = 2 * rand () - 1 ;

R = sqrt ( X*X + Y*Y ) ;

if ( R <= 1 )
{
M++ ;
S++ ;
}
else
{
S++ ;
}

}
cout << "Approximation de Pi: \n" << 4 * ( M/N ) << setprecision (5) ;
return 0;
}



EDIT 1 : Dans le debugger ça donne ca :

CODE
[Session started at 2007-11-20 18:25:20 +0100.]
Simulation de Pi
Entrez un nombre etier de simulations a effectuer.
10
Approximation de Pi:
-6.4226e+08
The Debugger has exited with status 0.


Qu'est ce qui ne va pas?
Et que me conseillez vous pour apprendre a maîtriser le C++? ( Livres , sites ET idées de projets etc... )
Gamoul
Je ne connais pas l'algorithme que tu utilises donc je sais pas si tu l'as correctement programmé, mais je vois un problème car tu n'initialise pas ta variable S à 0 au début.
Darknight670
CITATION(Gamoul @ 20 Nov 2007, 18:33) <{POST_SNAPBACK}>
Je ne connais pas l'algorithme que tu utilises donc je sais pas si tu l'as correctement programmé, mais je vois un problème car tu n'initialise pas ta variable S à 0 au début.


Je l'initialise en même temps que les autre au début de main () ce n'est pas bon?

CODE
double X ;
double Y ;
double R ;
int M ;
int S ;
atarxerxes
Ca c'est la déclaration, pas l'initialisation de sa valeur. En C tu n'es pas assuré de la valeur initiale d'une variable si tu ne le mets pas toi-même (par un S = 0; )
DBSor
Utilise le debugger, tu pourras suivre instruction par instruction ce que fait ton programme, c'est très instructif wink.gif
Acid
0) Initialisation de S indiqué par Gamoul
2) Le probleme:
Pour la methode de monte carlo il faut avoir des nombres dans [O;1] la fonction rand() retourne des nombre entre 0 et RAND_MAX (grand entier)
Pour avoir un rand entre 0 et 1 faire:
CODE
rand() / ((double) RAND_MAX);
3) test <=1 plutot <1 ici par rapport à l'algorithme utilisé (mais ce ne doit pas etre si important ici)
4) Sinon pour la forme:
etier => entier
pour le if j'ecrirai
CODE
if ( R < 1 )
      {M++;
      }
S++;
5) Test avec debugger (ou affichage des variables au minimum) indiqué par dbsor
6) La fonction rand n'est pas terrible, pour une utilisation dans le cadre d'algo du type Monte carlo on utilise une fonction plus sophistiquée ( loi uniforme, loi normale ...)

@+
Darknight670
CITATION(appleseed @ 20 Nov 2007, 21:00) <{POST_SNAPBACK}>
0) Initialisation de S indiqué par Gamoul
2) Le probleme:
Pour la methode de monte carlo il faut avoir des nombres dans [O;1] la fonction rand() retourne des nombre entre 0 et RAND_MAX (grand entier)
Pour avoir un rand entre 0 et 1 faire:
CODE
rand() / ((double) RAND_MAX);
3) test <=1 plutot <1 ici par rapport à l'algorithme utilisé (mais ce ne doit pas etre si important ici)
4) Sinon pour la forme:
etier => entier
pour le if j'ecrirai
CODE
if ( R < 1 )
      {M++;
      }
S++;
5) Test avec debugger (ou affichage des variables au minimum) indiqué par dbsor
6) La fonction rand n'est pas terrible, pour une utilisation dans le cadre d'algo du type Monte carlo on utilise une fonction plus sophistiquée ( loi uniforme, loi normale ...)

@+


2/ RAND_MAX doit être défini? ou pas besoin ?
4/ si on ne fait que if ( R < 1 ) il considerera que les pts a 1 cm du centre ne sont pas dans le cercle non? alors que si (d'après moi...)?

Mais merci a vous tous Gamoul , Appleseed et " Celui qui a un nom imprononçable" Aterxexes
macgic
Je ne suis plus certain mais il me semblait que la fonction rand renvoyait des réels entre 0 et 1. En tout cas, dans mes programmes, je n'ai jamais défini de RAND_MAX.

Pour ce qui est du point 4, effectivement, les points juste l'extérieur du disque ne sont pas pris en compte avec R <1. Ceci dit, probabilistement, c'est un événement de mesure nulle (donc proba que ça arrive = 0, du moins dans la théorie) donc ça ne changera rien du tout au résultat.
Acid
Exemple rand_max avec google (j'ai de la chance).
Darknight670
Désolé de vous embêter mais voila une autre de mes questions...
CODE
int main ( int argc , char * argv[] )
Cette ligne de code permet de récupérer des arguments mais si j'exécute mon programme comme ça :
CODE
monprogg.app -10000
Comment faire pour récupérer l'argument 10000? car
CODE
int Truc = argv [1]
ca ne peut pas marcher a cause des problèmes de conversions....
Acid
Comme tu l'indiques ici: int main ( int argc , char * argv[] ) les arguments sont des chaines de caracteres.
Si tu essayes cela: int Truc = argv [1] tu essaye de convertir directement une chaîne en un entier => message d'erreur.
La chaine 12 est code en memoire par le code ascii du 1 (sur un octet : 31) puis le code ascii du 2 (sur un octet:32) puis un code ascii 00
Ce qui donne en hexa: 31 32 00
L'entier 12 est codé en memoire par 00 00 00 OC
Comme tu peux le voir cela ne se ressemble pas il faut donc lancer une fonction pour faire la conversion:
int n = atoi(argv[1]);

@+
macgic
réponse éclair car je ne suis pas du tout sûr de moi (je n'utilise jamais argv, je mets toujours un cout et un cin pour entrer les paramètres tongue.gif ) mais il me semble que c'est argv[0] (premier élement du tableau).

Et est-ce que ça ne marche pas en castant la valeur (quitte à faire une gestion d'exception si soucis dans la conversion) ?
int Truc = (int) argv[0];
Acid
CITATION(macgic @ 22 Nov 2007, 19:30) <{POST_SNAPBACK}>
réponse éclair car je ne suis pas du tout sûr de moi (je n'utilise jamais argv, je mets toujours un cout et un cin pour entrer les paramètres tongue.gif ) mais il me semble que c'est argv[0] (premier élement du tableau).

Et est-ce que ça ne marche pas en castant la valeur (quitte à faire une gestion d'exception si soucis dans la conversion) ?
int Truc = (int) argv[0];


non, les casts sont des changements de representation entre nombre et aussi sur des adresses memoire (void* char* ...). Ici cela ne marchera pas...
Si tu as des doutes sur les arguments, le mieux pour comprendre est de faire afficher tous les arguments, argc te donne le nombre de ces arguments.
CODE
int i;
for (i =0;i<argc;i++)
printf("%d %s\n",i,argv[i]);

@+
Darknight670
Merci a tous j'ai réussi a le faire marcher ! Je ne sais pas pourquoi ça ne marchais pas donc je ne sais pas pourquoi il marche maintenant ... ( erreur de chiffres significatifs je crois...)
CODE
/* Importation de bibliothèques */
#include <iostream>
#include <stdlib.h>
#include <time.h>
#include <math.h>
#include <stdio.h>

using namespace std ;

int iChoix = 0 ;
/* -------------------------------------------------------------------------------------------------------------------- */
int iAlea ( void ) // Cette fonction genere un nb aleatoire....
{

static int first = 0;

if (first == 0)
{

srand (time ( NULL ) );
first = 1;

}
return ( rand () );
}
/* -------------------------------------------------------------------------------------------------------------------- */
double dExact( long int iPrecision )
{
/* Définition des variables */
double dPi = 0 ;
bool bAddition = true ;
long int liDiviseur = 3 ;
long int liCompteur = 0 ;


dPi = 1 - 1/ (double) liDiviseur;

cout << "Calcul de Pi en cours...\n"; /* Affichage d'un message en attendant que */
cout << "Svp patienter...\n\n" ; /* Pi soit calculé. */

/* Calcul de Pi */
do

{
liDiviseur = liDiviseur + 2;
if (bAddition == true)
{
dPi = dPi + 1/ (double) liDiviseur;
bAddition = false;
}

else

{
dPi = dPi - 1/ (double) liDiviseur;
bAddition = true;
}

liCompteur++;
}
while ( liCompteur <= iPrecision);

/* Affichage du résultat */
dPi = dPi * 4;
return dPi ;
}

/* -------------------------------------------------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------------------------------------------------- */

float fSimulationPi ( int iIteration )
{
float fCoordonneeX ;
float fCoordonneeY ;
float fLongueur ;
int iSimulation = 0 ;
int iPointCercle = 0 ;
int iPointTotal = 0 ;

while ( iSimulation <= iIteration )
{

iAlea () ;
fCoordonneeX = 2 * rand () / ( RAND_MAX + 1.0 ) ;
iAlea () ;
fCoordonneeY = 2 * rand () / ( RAND_MAX + 1.0 ) ;

fLongueur = sqrt (fCoordonneeX*fCoordonneeX + fCoordonneeY*fCoordonneeY) ;

if ( fLongueur < 1 )

{
iPointCercle++ ;
}

iSimulation++ ;
iPointTotal++ ;
}
return ( 4.00 * iPointCercle / iPointTotal ) ;
}

/* -------------------------------------------------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------------------------------------------------- */

int main ()
{

if ( iChoix == 0 )
{
cout << " ****************************\n" ;
cout << " * *\n" ;
cout << " * Pi Calculator *\n" ;
cout << " * Cree par Darknight670 *\n" ;
cout << " * Le 25/11/07 *\n" ;
cout << " * *\n" ;
cout << " ****************************\n" ;
}

cout << endl ;
cout << "Comment voulez vous calculez Pi?\n" ;
cout << "1.Par la methode Monte Carlo\n";
cout << "2.Grace au Theoreme de Leibniz\n" ;
cout << "0.Quitter\n" ;

cin >> iChoix ;

if ( iChoix == 1 )
{
cout << endl ;
cout << "Entrez un nombre de simulations a effectuer\n" ;

int iIteration ;
cin >> iIteration ;

cout << "Pi vaut : " << fSimulationPi ( iIteration ) ;
cout << endl ;

main () ;
}

if ( iChoix == 2 )
{

cout << endl ;
cout << "Entrez une precision de calcul\n" ;

int iPrecision ;
cin >> iPrecision ;

cout << "Pi vaut : " << dExact ( iPrecision ) ;
cout << endl;

main () ;

}

if ( iChoix == 0 )
{

cout << " Merci et au revoir!\n" ;
return 0 ;

}

return 1 ;
}

/* -------------------------------------------------------------------------------------------------------------------- */



Merci encore a tous
Acid
CITATION(Darknight670 @ 25 Nov 2007, 11:16) <{POST_SNAPBACK}>
Merci a tous j'ai réussi a le faire marcher ! Je ne sais pas pourquoi ça ne marchais pas donc je ne sais pas pourquoi il marche maintenant ... ( erreur de chiffres significatifs je crois...)

L'erreur provenait du fait que tu retournais un rand qui n'etait pas entre 0 et 1.
Au niveau de ton source:
La fonction Ilea ne sert à rien en fait.
Tu n'utilises pas le resultat retourne
Tu utilises une variable locale qui est mise à 0 puis testée => la fonction fait un srand chaque fois qu'elle est lancee..
Bref non utile.
=> enlever cette fonction et l'appel de cette fonction et mettre srand (time ( NULL ) ); en debut de ton programme.
et tu pourrais faire une fonction rand01 qui retourne une valeur entre 0 et 1.
Pour ne faire le srand qu'une fois comme dans ton code, c'est aussi possible mais dans ce cas il faut faire une variable globale (pas terrible de mon point de vue) toutefois voici une solution basée sur ton code:
CODE
static int first = 0;// En global
double rand01 ( void ) // Cette fonction genere un nb aleatoire....
{
if (first == 0)
{
srand (time ( NULL ) );
first = 1;
}
return rand () / ( RAND_MAX + 1.0 );
}
Ensuite modifies ton programme
CODE
iAlea ();
fCoordonneeX = 2 * rand () / ( RAND_MAX + 1.0 );
iAlea ();
fCoordonneeY = 2 * rand () / ( RAND_MAX + 1.0 );
Devient
CODE
fCoordonneeX = 2 * rand01();
fCoordonneeY = 2 * rand01();
@+
Ceci est une version "bas débit" de notre forum. Pour voir la version complète avec plus d'informations, la mise en page et les images, veuillez cliquer ici.
Invision Power Board © 2001-2025 Invision Power Services, Inc.