Re: [C++] Approssimazione di $pi$

Messaggioda Landau » 16/06/2018, 15:42

Ora torna tutto, grazie ad entrambi! Per il secondo punto, cosa ne pensate di quello che ho postato? Il dubbio resta ancora valido :roll:

Codice:
float *esperimentoPi(int nPunti, float a, int nMisure){

   float* results=new float[nMisure];
   for(unsigned int i=0; i<nMisure; i++){
      results[i]=misurePi(nPunti, a);
   }
   return &results;
}
Landau
Junior Member
Junior Member
 
Messaggio: 53 di 118
Iscritto il: 05/09/2017, 20:42

Re: [C++] Approssimazione di $pi$

Messaggioda Super Squirrel » 17/06/2018, 20:03

Nel secondo punto, dovrei salvare un certo numero di misure in un array dinamico:
Codice:
float *esperimentoPi(int nPunti, float a, int nMisure){

   float* results=new float[nMisure];
   for(unsigned int i=0; i<nMisure; i++){
      results[i]=misurePi(nPunti, a);
   }
   return &results;
}

Ho due dubbi essenziali: è corretto usare & per la variabile di return?

No, inoltre non compilerebbe quel codice perchè la funzione deve ritornare una variabile di tipo float*, mentre &results, essendo l'indirizzo di un puntatore a float, coincide col tipo float**.

E quando chiamo la funzione nel main con i parametri attuali, devo mettere l'*?

Non ho capito cosa intendi, magari posta il codice.

P.S.
Se le nMisure le fai una sola volta non vedo l'utilità di utilizzare una funzione esperimentoPi().
Chi dorme in democrazia, si sveglia in dittatura.
Super Squirrel
Senior Member
Senior Member
 
Messaggio: 229 di 1486
Iscritto il: 16/05/2013, 22:05

Re: [C++] Approssimazione di $pi$

Messaggioda Landau » 23/06/2018, 13:06

Ciao, scusa per il ritardo. In realtà dovrei fare Nmisure misure e salvarle nel vettore!

Edit: o meglio, dovrei fare Nmisure misure per ciascuna componente del vettore, credo...
Landau
Junior Member
Junior Member
 
Messaggio: 55 di 118
Iscritto il: 05/09/2017, 20:42

Re: [C++] Approssimazione di $pi$

Messaggioda Super Squirrel » 23/06/2018, 13:29

Ciao!
In realtà dovrei fare Nmisure misure e salvarle nel vettore!

Non ho capito il nesso logico di questa affermazione con il mio precedente post... :|

EDIT:
Edit: o meglio, dovrei fare Nmisure misure per ciascuna componente del vettore, credo...

Non mi è chiara come cosa...
In ogni caso dal punto di vista puramente informatico hai capito quello che intendevo nel post precedente?
Chi dorme in democrazia, si sveglia in dittatura.
Super Squirrel
Senior Member
Senior Member
 
Messaggio: 231 di 1486
Iscritto il: 16/05/2013, 22:05

Re: [C++] Approssimazione di $pi$

Messaggioda Landau » 23/06/2018, 17:32

Ok, ricomincio un attimo da capo, perché ormai è passato del tempo :lol:
Mi si chiede questo: Scrivere una funzione float *esperimentoPi(int nPunti, float a, int nMisure); che, creato dinamicamente un vettore di float di dimensione nMisure effettui nMisure misure di $π$ utilizzando la funzione misuraPi definita nell’esercizio precedente. Le misure dovranno essere salvate nel vettore creato dinamicamente, il cui indirizzo verrà restituito dalla funzione.

Quindi semplicemente dichiaro il vettore dinamico float* results=new float[nMisure];, lo carico con misure diverse di $pi$ for(unsigned int i=0; i<nMisure; i++){results[i]=misurePi(nPunti, a);} e lo restituisco con return results; . Per quanto riguarda il tuo post, effettivamente non ho capito cosa intendi. In qualche modo questa funzione la devo costruire perché me la richiede esplicitamente il testo, poi non so se sia effettivamente necessaria :-D

Il main deve fare questo:

Scrivere un programma che analizzi il comportamento della stima Monte Carlo in funzione dei punti usati in ciascuna misura di pi come segue.

1. Fissare il numero di misure per esperimento a NMISURE 50
2. Eseguire una sequenza di esperimenti al variare del numero di punti (parametro nPunti) tra 50 e 1000 con incrementi di 50.
3. Registrare il numero di punti usati, la media e la deviazione standard campionaria (!!!) degli esperimenti sul file risultatiPi.dat.


Quindi definisco la costante #define NMISURE 50 e faccio la serie di esperimenti usando la funzione di prima: for(unsigned j=1; j<=20; j++) esperimentoPi(50*j,a,NMISURE);. Apro il file con ofstream file_out; file_out.open("risultati.dat",ios::out);, uso le vecchie funzioni per calcolare media e deviazione standard e stampo tutto.

Questo è sommariamente quanto prodotto fino ad adesso, oltre alla funzione misuraPi :D
Landau
Junior Member
Junior Member
 
Messaggio: 56 di 118
Iscritto il: 05/09/2017, 20:42

Re: [C++] Approssimazione di $pi$

Messaggioda Landau » 23/06/2018, 18:09

Quindi alla fine il main verrebbe più o meno così:

Codice:
int main(){

   srand(time(NULL));
        ofstream file_out;
   file_out.open("risultati.dat",ios::out);

   
   for(unsigned j=1; j<=20; j++)
      esperimentoPi(50*j,a,NMISURE);

      file_out << "Numero dati:" << 50*j << ", Media: " << media(results, nMisure) << " ,
                Deviazione Standard:" << devStd(results, nMisure) << endl;

   return 0;
}
Landau
Junior Member
Junior Member
 
Messaggio: 57 di 118
Iscritto il: 05/09/2017, 20:42

Re: [C++] Approssimazione di $pi$

Messaggioda vict85 » 26/06/2018, 21:07

Quel main ha molti errori. Per esempio non si capisce come stai riempendo il vettore results, o come mai nMisure sia ogni tanto maiuscolo e ogni tanto no. Inoltre hai dimenticato le parentesi nel for e quindi la stampa nel file non è inclusa nel ciclo. Tra l'altro non hai chiamato delete sulla memoria che hai allocato dentro esperimento Pi.

Per capirci, questo è il main nella "mia versione":
Codice:
#include <stdlib.h>
#include <fstream>
#include <iostream>  // cerr
#include <time.h>
#include <cmath>

float misuraPi(int nPunti, float);

float * esperimentoPi(int nPunti, float a, int nMisure);

float media(const float * array, int N);

float devStd(const float * array, int N, const float * media_ptr = nullptr);

inline void
delete_array_of_array(float * array[], int N)
{
  for (int i = 0; i != N; i++)
    {
      delete[] array[i];
      array[i] = nullptr;
    }
}

int
main( )
{
  constexpr int NMISURE = 50;
  constexpr int NRIPETIZIONI = 1000 / 50;
  constexpr float a = 1.f;
  srand(time(nullptr));  // nullptr e' type safe

  float * esperimenti[NRIPETIZIONI];

  for (int i = 0, nPunti = 50; i != NRIPETIZIONI; ++i, nPunti += 50)
    {
      esperimenti[i] = esperimentoPi(nPunti, a, NMISURE);
      if (!esperimenti)
        {
          std::cerr << "Errore in esperimentoPi" << std::endl;
          delete_array_of_array(esperimenti, i);
          return EXIT_FAILURE;
        }
    }

  std::ofstream file_out;
  file_out.open("risultati.dat", std::ios::out);
  if (file_out.fail( ))
    {
      std::cerr << "Errore nella creazione del file" << std::endl;
      delete_array_of_array(esperimenti, NRIPETIZIONI);
      return EXIT_FAILURE;
    }

  for (int i = 0, nPunti = 50; i != NRIPETIZIONI; ++i, nPunti += 50)
    {
      float m = media(esperimenti[i], NMISURE);
      file_out << "Numero dati: " << nPunti << ", Media: " << m
               << ", Deviazione Standard: "
               << devStd(esperimenti[i], NMISURE, &m) << std::endl;
    }
  delete_array_of_array(esperimenti, NRIPETIZIONI);
}
dove ovviamente ho omesso le funzioni che ti viene richiesto di implementare. Ho diviso calcolo e scrittura su file apposta per mostrarti qualcosa di diverso. Altri approcci sono possibili, per esempio questo:
Codice:
#include <stdlib.h>
#include <fstream>
#include <iostream>  // cerr
#include <time.h>
#include <cmath>

float misuraPi(int nPunti, float);

float * esperimentoPi(int nPunti, float a, int nMisure);

float media(const float * array, int N);

float devStd(const float * array, int N, const float * media_ptr = nullptr);

int
main( )
{
  constexpr int NMISURE = 50;
  constexpr float a = 1.0f;
  srand(time(nullptr));  // nullptr e' type safe

  std::ofstream file_out;
  file_out.open("risultati.dat", std::ios::out);
  if (file_out.fail( ))
    {
      std::cerr << "Errore nella creazione del file" << std::endl;
      return EXIT_FAILURE;
    }

  for (int nPunti = 50; nPunti < 1001; nPunti += 50)
    {
      float const * esperimento = esperimentoPi(nPunti, a, NMISURE);
      if (!esperimento)
        {
          std::cerr << "Errore in esperimentoPi" << std::endl;
          return EXIT_FAILURE;
        }

      float m = media(esperimento, NMISURE);
      file_out << "Numero dati: " << nPunti << ", Media: " << m
               << ", Deviazione Standard: " << devStd(esperimento, NMISURE, &m)
               << std::endl;
      // un po' uno spreco, sarebbe più pratico allocare una volta e
      // riutilizzare
      delete[] esperimento;
    }
}
o anche
Codice:
#include <stdlib.h>
#include <fstream>
#include <iostream>  // cerr
#include <time.h>
#include <cmath>

float misuraPi(int nPunti, float);

float * esperimentoPi(int nPunti, float a, int nMisure);

float media(const float * array, int N);

float devStd(const float * array, int N, const float * media_ptr = nullptr);

inline void
delete_array_of_array(float * array[], int N)
{
  for (int i = 0; i != N; i++)
    {
      delete[] array[i];
      array[i] = nullptr;
    }
}

int
main( )
{
  constexpr int NMISURE = 50;
  constexpr int NRIPETIZIONI = 1000 / 50;
  constexpr float a = 1.f;
  srand(time(nullptr));  // nullptr e' type safe

  float esperimenti[NRIPETIZIONI][2];

  for (int i = 0, nPunti = 50; i != NRIPETIZIONI; ++i, nPunti += 50)
    {
      float * esperimento = esperimentoPi(nPunti, a, NMISURE);
      if (!esperimento)
        {
          std::cerr << "Errore in esperimentoPi" << std::endl;
          return EXIT_FAILURE;
        }
      esperimenti[i][0] = media(esperimento, NMISURE);
      esperimenti[i][1] = devStd(esperimento, NMISURE, &esperimenti[i][0]);

      // che spreco di memoria...
      delete[] esperimento;
    }

  std::ofstream file_out;
  file_out.open("risultati.dat", std::ios::out);
  if (file_out.fail( ))
    {
      std::cerr << "Errore nella creazione del file" << std::endl;
      return EXIT_FAILURE;
    }

  for (int i = 0, nPunti = 50; i != NRIPETIZIONI; ++i, nPunti += 50)
    {
      file_out << "Numero dati: " << nPunti << ", Media: " << esperimenti[i][0]
               << ", Deviazione Standard: " << esperimenti[i][1] << std::endl;
    }
}


I codici sono stati messi in ordine abbastanza sparso. L'ultimo è quello che preferisco. Il codice richiede di essere compilato con l'opzione --std=c++11 per l'uso dei constexpr, puoi anche trasformarli in dei #define o in dei const.

Comunque l'approccio è piuttosto inefficiente: il codice produce qualcosa come
Codice:
Numero dati: 50, Media: 3.12, Deviazione Standard: 0.191332
Numero dati: 100, Media: 3.1976, Deviazione Standard: 0.189553
Numero dati: 150, Media: 3.112, Deviazione Standard: 0.127024
Numero dati: 200, Media: 3.1508, Deviazione Standard: 0.117997
Numero dati: 250, Media: 3.14432, Deviazione Standard: 0.127368
Numero dati: 300, Media: 3.1312, Deviazione Standard: 0.106178
Numero dati: 350, Media: 3.12777, Deviazione Standard: 0.0758926
Numero dati: 400, Media: 3.132, Deviazione Standard: 0.0843564
Numero dati: 450, Media: 3.14009, Deviazione Standard: 0.0776913
Numero dati: 500, Media: 3.14832, Deviazione Standard: 0.0704584
Numero dati: 550, Media: 3.136, Deviazione Standard: 0.0728145
Numero dati: 600, Media: 3.12987, Deviazione Standard: 0.0595277
Numero dati: 650, Media: 3.14769, Deviazione Standard: 0.0618607
Numero dati: 700, Media: 3.14046, Deviazione Standard: 0.0595722
Numero dati: 750, Media: 3.13696, Deviazione Standard: 0.0575969
Numero dati: 800, Media: 3.1366, Deviazione Standard: 0.0685525
Numero dati: 850, Media: 3.136, Deviazione Standard: 0.0623809
Numero dati: 900, Media: 3.14018, Deviazione Standard: 0.0583372
Numero dati: 950, Media: 3.13651, Deviazione Standard: 0.0692006
Numero dati: 1000, Media: 3.16048, Deviazione Standard: 0.0420867


Insomma hai bisogno di una buona funzione di numeri casuali per avere risultati accettabili.
vict85
Moderatore
Moderatore
 
Messaggio: 9315 di 19253
Iscritto il: 16/01/2008, 00:13
Località: Berlin

Precedente

Torna a Informatica

Chi c’è in linea

Visitano il forum: Nessuno e 1 ospite

cron