PDA

Visualizza la versione completa : Numeri random Gaussiani( C / C++)


zalma
25-04-2004, 11:50
Sto facendo un programma per la tesi, qualcuno sa se il C ( C++) ha una funzione tipo RANNOR() , che genera numeri random secondo una distribuzione gaussiana ( media 0, var 1) ?
please help me!!!

anx721
25-04-2004, 19:54
Tempo fa avevo risposto ad una domanda simile in questo thread:

http://forum.html.it/forum/showthread.php?s=&threadid=604283&highlight=gaussiana

avevo postato un link ad una libreria c++ che conteneva una simile funzione, se no puoi costruirtela da te tenendo presente che se generi numeri random con distribuzione lineare, per ottenere una distribuzione gaussiana basta considerare ad esempio la la media di 10 numeri. Cio per generare un numero con distribuzione gaussiana ne generi 10 con distribuzione lineare, li sommi e dividi per 10: la maggior parte dei numeri cosi prodotti si affolleranno attorno al valore di picco, avevo anche messo un semplice algortimo che lo faceva.

:ciauz:

zalma
25-04-2004, 23:01
T ringrazio; il punto ke mi serve di poter avere un valore preciso per la deviazione standard, quindi nn posso utilizzare un algoritmo fatto in casa ( e nemmeno metodi monte carlo); tra l'altro sono alle prime armi col C++, puoi darmi una mano ad usare l'indicazione del getGaussianFloat che mi hai dato? grazie e scusa il disturbo

anx721
26-04-2004, 13:47
Il link esatto :

http://manitou.gel.ulaval.ca/~parizeau/doc/a00092.html


Quel sito mostra un insieme di file c++ in cui sono definite varie classi, scritte da Marc Parizeau, un professore di un 'universita francese.

In particolare ha definito una classe NumberGenerator che offre una funzione getGaussianFloat() per avere i numeri con distribuzione gaussiana; la funzione getGaussianFloat genera numeri gaussiani con media zero e deviazione standard pari a 1; se vuoi puoi cambiare questi valori passandoli alla funzione: getGaussianFloat(media, devStand);

Per usare la classe fai cosi: creati un file NumberGenerator.cpp in cui metterai il codice che ti metto dopo, poi nella stessa cartella in cui c' il NumberGenerator.cpp mettici un altro file NumberGenerator.hpp, in cui inserirai il codice che ti metto dopo. Quindi per usare il generatore di numeri casuali basta includerti il file header NumberGenerator.hpp, creare un oggetto NumberGenerator e invocarci la funzione getGaussianFloat():



#include "NumberGenerator.hpp"
....
....
...

//Creo il NumberGenerator
NumberGenerator gen;
double d;
//Genero il numero casuale
d = gen.getGaussianFloat();




****************************************
CODICE PER IL FILE NumberGenerator.cpp
****************************************



#include "NumberGenerator.hpp"
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include <iostream>
#include <fstream>

using namespace std;

NumberGenerator rand1;

NumberGenerator::NumberGenerator(void)
{
ifstream lStream("rand1.seed");
if(lStream.good()) lStream >> idum;
else idum = time(0);
for(int j=NTAB+7; j >= 0; --j)
{
long k = idum/IQ;
idum = IA*(idum-k*IQ)-IR*k;
if(idum < 0) idum += IM;
if(j < NTAB) iv[j] = idum;
}
iy = iv[0];
iset = 0;
}

NumberGenerator::NumberGenerator(unsigned long inSeed
)
{
idum = inSeed;
for(int j=NTAB+7; j >= 0; --j)
{
long k = idum/IQ;
idum = IA*(idum-k*IQ)-IR*k;
if(idum < 0) idum += IM;
if(j < NTAB) iv[j] = idum;
}
iy = iv[0];
iset = 0;
}

NumberGenerator::~NumberGenerator(void)
{
ofstream lStream("rand1.seed");
if(!lStream.good()) cerr << "Unable to create file \"rand1.seed\"!" << endl;
else lStream << idum;
}

int NumberGenerator::getUniformInteger(int inFirst,
int inLast
)
{
int lNumber = (int) (inFirst + (inLast - inFirst + 1) * getUniformFloat());
if(lNumber > inLast) lNumber = inLast;
return lNumber;
}

double NumberGenerator::getUniformFloat(double inFirst,
double inLast
)
{
double lTmp, lNumber;

long k = idum/IQ;
idum = IA*(idum-k*IQ)-IR*k;
if(idum < 0) idum += IM;
int j = (int) iy/NDIV;
iy = iv[j];
iv[j] = idum;
if((lTmp=AM*iy) > RNMX) lNumber = RNMX;
else lNumber = lTmp;
return inFirst + (inLast - inFirst) * lNumber;
}

double NumberGenerator::getGaussianFloat(double inMean,
double inStdDev
)
{
double fac, rsq, v1, v2;

if(iset == 0) {
do {
v1 = 2.0*getUniformFloat() - 1.0;
v2 = 2.0*getUniformFloat() - 1.0;
rsq = v1*v1+v2*v2;
} while(rsq >= 1.0 || rsq == 0);
fac = sqrt(-2.0*log(rsq)/rsq);
gset = v1*fac;
iset = 1;
return v2*fac*inStdDev + inMean;
} else {
iset = 0;
return gset*inStdDev + inMean;
}
}



****************************************
CODICE PER IL FILE NumberGenerator.hpp
****************************************



#ifndef Data_NumberGenerator_hpp_
#define Data_NumberGenerator_hpp_

#define IA 16807
#define IM 2147483647
#define AM (1.0/IM)
#define IQ 127773
#define IR 2836
#define NTAB 32
#define NDIV (1+(IM-1)/NTAB)
#define EPS 1.2e-7
#define RNMX (1.0-EPS)


class NumberGenerator
{
public:
NumberGenerator(void);
NumberGenerator(unsigned long inSeed);
~NumberGenerator(void);

int operator()(unsigned long inValue) {return getUniformInteger(0, inValue-1);}

unsigned int getCurrentSeed(void) {return idum;}
bool getUniformBool(void) {return getUniformInteger(0,1);}
int getUniformInteger(int inFirst, int inLast);
double getUniformFloat(double inFirst=0., double inLast=1.0);
double getGaussianFloat(double inMean=0, double inStdDev=1);

private:
long iy;
long iv[NTAB];
long idum;

int iset;
double gset;

};

extern NumberGenerator rand1;

#endif



:ciauz:

zalma
27-04-2004, 22:28
ottimo, funziona...grazie!

Loading