Esercizio Costruiamo un generatore di numeri random, per esempio
Transcript
Esercizio Costruiamo un generatore di numeri random, per esempio
Esercizio
Costruiamo un generatore di numeri
random, per esempio secondo una
gaussiana.
Per generare una generatore di numeri
random distribuiti secondo una gaussiana
usiamo un metodo semplice e
sufficientemente preciso: il metodo BoxMuller. See Numerical Receipies in
Fortran,C o C++ chapter 7.2
F.S. Cafagna, Linguaggi di programmazione avanzati: C++ , XXIII ciclo
265
Esercizio
Di solito in quasi tutti i linguaggi di
programmazione abbiamo a disposizione un
generatore di numeri random secondo una
distribuzione piatta, ovvero con una
distribuzione di probabilità uniforme di generare
un numero tra x e x+dx:
⎧dx 0 < x < 1
p ( x)dx = ⎨
⎩0 per ogni altro valore
Essendo la probabilità normalizzata:
∞
∫ p( x)dx = 1
−∞
F.S. Cafagna, Linguaggi di programmazione avanzati: C++ , XXIII ciclo
266
Esercizio
Nel caso del C e del C++ abbiamo un
generatore che genera numeri random, fino a
RAND_MAX (macro di preprocessore): rand()
Quindi, se si desidera una variabile uniforme
nell’intervallo [0,1[, di solito si definisce:
#define DRAND(PAR) rand()/(double)RAND_MAX
E’ anche possibile definire il seme di partenza
usando: sran( int )
F.S. Cafagna, Linguaggi di programmazione avanzati: C++ , XXIII ciclo
267
Esercizio
Supponiamo di sapere generare in modo
uniforme x, e consideriamo una funzione:
y (x)
la sua distribuzione di probabilità sara:
p ( y )dy
ovvero:
p ( y )dy = p ( x)dx
dx
p( y ) = p( x)
dy
F.S. Cafagna, Linguaggi di programmazione avanzati: C++ , XXIII ciclo
268
Esercizio
Quindi se la probabilità di una distribuzione
arbitraria è una funzione positiva, invertibile
e normalizzata ad 1, avremo:
p( y) = f ( y)
∞
∫
f ( y) = 1
−∞
dx
= f ( y)
dy
La soluzione dell’ultima
eq. differenziale:
y
y
x = F ( y ) = ∫ f ( y )dy = ∫ p ( y )dy
0
0
F.S. Cafagna, Linguaggi di programmazione avanzati: C++ , XXIII ciclo
269
Esercizio
Quindi la trasformazione che da una
distribuzione uniforme ci porta ad una
distribuita secondo f ( y ) è:
−1
y ( x) = F ( x)
−1
essendo F la funzione inversa di F .
Tutto dipende dall’invertibilità dell’integrale
di f ( y ) e dalla sua calcolabilità (numerica o
analitica)
F.S. Cafagna, Linguaggi di programmazione avanzati: C++ , XXIII ciclo
270
Esercizio
C’è una semplice interpretazione geometrica.
F ( y ) altri non è che l’area sotto la curva di
probabilità a sinistra di y .
Quindi devo:
Scegliere x random
Trovare il valore y
per cui l’integrale
della curva di probabilità
vale x
F.S. Cafagna, Linguaggi di programmazione avanzati: C++ , XXIII ciclo
271
Esercizio
Nel caso del metodo Box-Muller, partiamo da:
2
y
−
1
p ( y ) dy =
e 2 dy
2π
E consideriamo l’estensione del metodo
precedente in più dimensioni:
p ( y 1 , y 2 , K ) dy 1 dy 2 K =
∂ (x1 , x 2 , K )
dy 1 dy 2 K
p ( x1 , x 2 , K )
∂ ( y1 , y 2 , K )
F.S. Cafagna, Linguaggi di programmazione avanzati: C++ , XXIII ciclo
272
Esercizio
E consideriamo:
y1 =
− 2 ln x 1 cos( 2 π x 2 )
y2 =
− 2 ln x 1 sin( 2 π x 2 )
Queste le possiamo invertire:
⎡ 1
x 1 = exp ⎢ − ( y 12 +
⎣ 2
⎛ y2
1
x2 =
arctan ⎜⎜
2π
⎝ y1
⎤
y )⎥
⎦
⎞
⎟⎟
⎠
2
2
F.S. Cafagna, Linguaggi di programmazione avanzati: C++ , XXIII ciclo
273
Esercizio
Lo Jacobiano diventa quindi:
∂ x1
∂ ( x1 , x 2 )
∂ y1
=
∂x2
∂ ( y1 , y 2 )
∂ y1
⎡
−⎢
⎢⎣
1
e
2π
y 12
−
2
⎤⎡
⎥⎢
⎥⎦ ⎢⎣
∂ x1
∂y2
=
∂x2
∂y2
1
e
2π
y 22
−
2
⎤
⎥
⎥⎦
F.S. Cafagna, Linguaggi di programmazione avanzati: C++ , XXIII ciclo
274
Esercizio
Possiamo generare x1 e x 2 indipendentemente
per ottenere le due y 1 e y 2
Se consideriamo le variabili trigonometriche:
R 2 ≡ v12 + v 22 → x1
angle ( v 1 , v 2 ) → 2 π x 2
Possiamo scrivere:
(
− 2 ln x (v
y1 =
− 2 ln x 1 v 1 /
y2 =
/
1
2
)
R )
R2
2
F.S. Cafagna, Linguaggi di programmazione avanzati: C++ , XXIII ciclo
275
Esercizio
In breve:
Generiamo v 1 e v 2 nel quadrato di lati [-1,1]
Controlliamo che siano nella circonferenza unitaria
Calcoliamo y 1 e y 2 con la trasformazione di BoxMuller:
(
− 2 ln x (v
y1 =
− 2 ln x 1 v 1 /
y2 =
/
1
2
)
R )
R2
2
Ritorniamo un valore e salviamo l’altro per il
passaggio successivo.
F.S. Cafagna, Linguaggi di programmazione avanzati: C++ , XXIII ciclo
276
Esercizio
double v1,v2,rsq,fac,g;
switch(_flag){
case 0:
// Generate two new random number
rsq=2.;
while( (rsq>=1.) || (rsq==0.) ){
v1=2.*DRAND()-1.;
v2=2.*DRAND()-1.;
rsq=pow(v1,2.)+pow(v2,2.);
}
fac=sqrt(-2.*log(rsq)/rsq);
_g1=v1*fac;
_g2=v2*fac;
_flag=1;
g=_g1;
break;
case 1:
g=_g2;
_flag=0;
break;
default:
std::cout << " gaussrnd::Grnd flag error ! _flag= "
<< _flag << std::endl;
break;
}
return g;
F.S. Cafagna, Linguaggi di programmazione avanzati: C++ , XXIII ciclo
277
Esercizio
#ifndef GAUSSRND_H
#define GAUSSRND_H
#include <iostream>
#include <cstdlib>
#include <cmath>
#define DRAND(PAR) rand()/(double)RAND_MAX
#define SRAND(PAR) srand(PAR)
#define RANGEN
// To generate a normal distributed Gaussian rand number
// distribution using the Box-Muller method. See Numerical Receipies
// in Fortran, chapter 7.2
class gaussrnd{
private:
int _flag;
int _seed;
double _g1,_g2;
public:
// Init the rand48 random number generator
gaussrnd(const int &seed=0 ): _flag(0) {NewSeq(seed);}
// Inizialize a new random sequence
void NewSeq(const int &seed) {_seed=seed; SRAND(_seed);}
double Grnd();
void Print();
};
#endif //GAUSSRND_H
F.S. Cafagna, Linguaggi di programmazione avanzati: C++ , XXIII ciclo
278
Esercizio
#include "gaussrnd.h"
double gaussrnd::Grnd(){
double v1,v2,rsq,fac,g;
switch(_flag){
}
case 0:
// Generate two new random number
rsq=2.;
while( (rsq>=1.) || (rsq==0.) ){
v1=2.*DRAND()-1.;
v2=2.*DRAND()-1.;
rsq=pow(v1,2.)+pow(v2,2.);
}
fac=sqrt(-2.*log(rsq)/rsq);
_g1=v1*fac;
_g2=v2*fac;
_flag=1;
g=_g1;
break;
case 1:
g=_g2;
_flag=0;
break;
default:
std::cout << " gaussrnd::Grnd flag error ! _flag= "
<< _flag << std::endl;
break;
}
return g;
void gaussrnd::Print() {
std::cout << " gaussrnd::Print max random number: " << RAND_MAX << std::endl
<< "
Seed : " << _seed << std::endl;
}
F.S. Cafagna, Linguaggi di programmazione avanzati:
C++ , XXIII ciclo
279
Esercizio
Adesso che abbiamo il nostro generatore
random, come facciamo a controllarne il
risultato, i.e. a vedere la distribuzione ?
Costruiamo un istogramma !!
F.S. Cafagna, Linguaggi di programmazione avanzati: C++ , XXIII ciclo
280
Esercizio
Immaginiamo una semplice classe
con un massimo, un minimo ed un numero di divisioni:
struct simple{
double xmin_,xmax_;
int bin_;
};
e pensiamo ad un metodo:
int simple::Bin( double x ) {
return (x>=max_) ? (bin_+1): int( ((x-min_)/((max_-min_)/bin_));
}
Questo metodo, dato un valore x, ritorna:
bin_+1, se x è maggiore o uguale di max_
un intero tra 1 e bin_, se x è maggiore di min_ e minore di
max_
Un numero minore uguale a 0 se x è minore o uguale a min_
F.S. Cafagna, Linguaggi di programmazione avanzati: C++ , XXIII ciclo
281
Esercizio
Immaginiamo una semplice classe
con un massimo, un minimo ed un numero di divisioni:
struct simple{
double xmin_,xmax_;
int bin_;
};
e pensiamo ad un metodo:
int simple::Bin( double x ) {
return (x>=max_) ? (bin_+1): int( ((x-min_)/((max_-min_)/bin_));
}
Questo metodo, dato un valore x, ritorna:
bin_+1, se x è maggiore o uguale di max_
un intero tra 1 e bin_, se x è maggiore di min_ e minore di
max_
Un numero minore uguale a 0 se x è minore o uguale a min_
F.S. Cafagna, Linguaggi di programmazione avanzati: C++ , XXIII ciclo
282
Esercizio
Quindi se scrivo:
int Max(const int a, const int b) const {
return ( a<b) ? b: a; }
Posso riscrivere Bin:
int simple::Bin( double x ) {
return Max(
(x>=max_) ? (bin_+1): int( ((x-min_)/((max_-min_)/bin_)), 0 );
}
Adesso Bin(x), dato un valore x, ritorna:
bin_+1, se x è maggiore o uguale di max_
un intero tra 1 e bin_, se x è maggiore di min_ e minore di
max_
Un numero uguale a 0 se x è minore o uguale a min_
F.S. Cafagna, Linguaggi di programmazione avanzati: C++ , XXIII ciclo
283
Esercizio
Quindi questo oggetto dato un range: ]min_, max_[, ed un
numero di bin: bin_, ritorna il numero di bin di un valore
qualsiasi: x
Se gli aggiungo un titolo, posso utilizzarlo come asse
dell’istogramma:
class axis {
public:
int Bin(double x) ;
private:
int Max(const int a, const int b) const ;
double max_;
double min_;
int bin_;
string title_;
};
F.S. Cafagna, Linguaggi di programmazione avanzati: C++ , XXIII ciclo
284
Esercizio
Completandola con setters, getters e Print():
class axis {
public:
int Bin(double x) ;
double GetMax() const { return
max_; }
double GetMin() const { return
min_; }
int GetBin() const { return bin_; }
const char * GetTitle() const {
return title_.c_str(); }
void SetMax( double x ) { max_ =
x; }
void SetMin( double x ) { min_ = x;
}
void SetBin( int x ) { bin_ = x; }
void SetTitle( const char *x ) {
title_=x; }
void SetTitle( const string & x ) {
SetTitle(x.c_str() ) ; }
void Print() const;
private:
int Max(const int a, const int b)
const ;
double max_;
double min_;
int bin_;
string title_;
};
F.S. Cafagna, Linguaggi di programmazione avanzati: C++ , XXIII ciclo
285
Esercizio
Potrebbe tornare comodo il metodo inverso di Bin():
#define BINERROR -999999.
#define UNDERFLOW -1111111.
#define OVERFLOW 111111.
double axis::GetBinMin( const int i ) const {
if(!i) return UNDERFLOW;
if(i==bin_+1) return OVERFLOW;
return (i<=bin_) ? double(min_+(i-1)*(((max_min_)/bin_))) : BINERROR;
}
Questo metodo dato un intero i ritorna:
-1111111., se i è pari a 0, UNDERFLOW;
1111111., se i è pari a bin_+1, OVERFLOW;
-999999., se i è maggiore di bin_+1, BINERROR;
un valore compreso tra min_ e max_ se i e compreso tra 1 e bin_
Quindi calcolare l’estremo superiore:
double GetBinMax( const int i ) const { return GetBinMin(i+1);
}
F.S. Cafagna, Linguaggi di programmazione avanzati: C++ , XXIII ciclo
286
Esercizio
Quindi la class definition finale diventa:
#ifndef AXIS_H
#define AXIS_H
#include <iostream>
#define BINERROR -999999.
#define UNDERFLOW -1111111.
#define OVERFLOW 111111.
using std::string;
using std::cout;
using std::endl;
class axis {
public:
int Bin(double x) ;
double GetMax() const { return max_; }
double GetMin() const { return min_; }
int GetBin() const { return bin_; }
deouble GetBinMin) const int I ) const;
double GetBinMax( const int i ) const
{ return GetBinMin(i+1); }
const char * GetTitle() const { return
title_.c_str(); }
const char * GetTitle() const { return
title_.c_str(); }
void SetMax( double x ) { max_ = x; }
void SetMin( double x ) { min_ = x; }
void SetBin( int x ) { bin_ = x; }
void SetTitle( const char *x ) { title_=x; }
void SetTitle( const string & x ) {
SetTitle(x.c_str() ) ; }
void Print() const;
private:
int Max(const int a, const int b)
const ;
double max_;
double min_;
int bin_;
string title_;
axis.h
};
# endif //AXIS_H
F.S. Cafagna, Linguaggi di programmazione avanzati: C++ , XXIII ciclo
287
Esercizi
Quindi un istogramma
potrebbe essere fatto :
typedef vector <int> vint;
class hist {
Crea un vector di interi
public:
hist(double xmax=1., double xmin=0., int bin=100,
const char *t="none", const char *at="none"):
xaxis_(xmax,xmin,bin,at), count_(bin+2), entries_(0), title_(t) {};
bool Fill(double x){ int i=xaxis_.Bin(x);
if(i<=count_.size()) {
count_[i]++;
entries_++;
return true;
}
return false;
}
Sfrutta Bin(int) di axis per
calcolare il numero di bin che
sarà l’i-esimo oggetto contenuto
nel vector
private:
vint count_;
axis xaxis_;
int entries_;
string title_;
};
F.S. Cafagna, Linguaggi di programmazione avanzati: C++ , XXIII ciclo
288
Esercizi
Notare l’utilizzo del costruttore di
vector in cui viene specificato il
numero di elementi iniziali da creare:
hist(double xmax=1., double xmin=0., int bin=100,
const char *t="none", const char *at="none"):
xaxis_(xmax,xmin,bin,at), count_(bin+2), entries_(0),
title_(t) {};
count_(bin+2) è equivalente a:
vector <int, (bin+2) > // crea un vector che contiene
inizialmente (bin+2) oggetti di tipo int
F.S. Cafagna, Linguaggi di programmazione avanzati: C++ , XXIII ciclo
289
Esercizio
Al solito con getters e setters avremo:
// Getters
int GetEntries() const { return entries_; }
int GetNbin() const { return xaxis_.GetBin(); }
double GetXmax() const { return xaxis_.GetMax(); }
double GetXmin() const { return xaxis_.GetMin(); }
const char * GetTitle() const { return title_.c_str(); }
const char * GetATitle() const { return xaxis_.GetTitle(); }
#ifndef HIST_H
#ifndef HIST_H
#define HIST_H
#include <vector>
#include <string>
#include "axis.h"
using std::vector;
using std::string;
typedef vector <int> vint;
class hist {
public:
hist(double xmax=1., double xmin=0., int bin=100,
const char *t="none", const char *at="none"):
xaxis_(xmax,xmin,bin,at), count_(bin+2), entries_(0),
title_(t) {};
bool Fill(double x){ int i=xaxis_.Bin(x);
if(i<=count_.size()) {
count_[i]++;
entries_++;
return true;
}
return false;
}
// Setters
void SetNbin( const int i ) { xaxis_.SetBin(i); }
void SetXmax( const double i ) { xaxis_.SetMax(i); }
void SetXmin( const double i ) { xaxis_.SetMin(i); }
void SetTitle( const char *c ) { title_=c; }
void SetATitle( const char *c) { xaxis_.SetTitle(c); }
private:
vint count_;
axis xaxis_;
int entries_;
string title_;
};
#endif // HIST_H
hist.h
F.S. Cafagna, Linguaggi di programmazione avanzati: C++ , XXIII ciclo
290
Esercizio
Rimane il problema di stampare il contenuto:
void Print( ostream &o = cout) const {
o << " Histo : " << title_ << endl;
o << " Underflow : " << *count_.begin()
<< ", Overflow : " << *count_.end() << endl;
for( int i=0; i<(count_.size()); PrintBin(i++,o) );
}
void PrintBin( const int I, ostream &o) const {
o << " Bin : " << i << ", " << xaxis_.GetBinMin(i)
<< ", " << count_[i] << endl;
}
Notare la generalizzazione dell’output stream. In questo
modo sarà possibile usare un file-stream invece di cout
e salvare l’output su file
F.S. Cafagna, Linguaggi di programmazione avanzati: C++ , XXIII ciclo
291
Esercizio
In questo modo viene stampato il contenuto di
ogni bin, ma possiamo pensare ad un modo per
ottenere un “grafico” ?
Se abbiamo a disposizione MAXCHAR colonne
su un terminale ASCII, potremmo pensare di
scrivere una stringa lunga L dove:
MAXCHAR:L=max_bin_content:bin_content
Quindi una volta calcolato il massimo contenuto
nei bin, potremo calcolare il fattore di scala:
MAXCHAR/max_bin_content
E calcolare:
L=bin_content*(MAXCHAR/max_bin_content)
F.S. Cafagna, Linguaggi di programmazione avanzati: C++ , XXIII ciclo
292
Esercizio
Per calcolare il massimo conteggio nel bin,
possiamo usare un algoritmo della STL:
max_element
E’ dichiarato nell’header: algorithm
E la sua dichiarazione recita:
template <class ForwardIterator> ForwardIterator max_element (
ForwardIterator first, ForwardIterator last );
template <class ForwardIterator, class Compare> ForwardIterator
max_element ( ForwardIterator first, ForwardIterator last, Compare
comp );
Quindi dati due iteratori, controlla il valore di
tutti gli oggetti a cui gli iteratori puntano e
ritorna l’iteratore che punta all’oggetto con il
contenuto maggiore secondo la classe di
comparazione comp
F.S. Cafagna, Linguaggi di programmazione avanzati: C++ , XXIII ciclo
293
Esercizio
Per cui, nella nostra classe hist potremmo
scrivere:
int maxele=*(max_element(
count_.begin()+1, count_.end()-1));
Una volta calcolato il massimo contenuto nel bin,
possiamo calcolare Il fattore di scala e stampare
una linea che contiene un numero di caratteri
proporzionale al contenuto del bin.
Per questo sfruttiamo le proprietà delle
stringstream ed il creatore non di default delle
string
F.S. Cafagna, Linguaggi di programmazione avanzati: C++ , XXIII ciclo
294
Esercizio
void Print( ostream & o=cout,) const {
int maxele=*(max_element( count_.begin()+1, count_.end()-1));
o << " Histo : " << title_ << endl;
o << " Max value : " << maxele << endl;
Calcolo
o << " Underflow : " << *count_.begin()
<< ", Overflow : " << *count_.end() << endl;
for( int i=0; i<(count_.size()); PrintBin(i++,o) );
for( int i=1; i<(count_.size()-1); PrintBin(i++, o, MAXCHAR/maxele ) );
}
il massimo
// scale, must be equal to MAXCHAR / MAXELE
void PrintBin( const int i, ostream &o=cout, double scale=0 ) const {
if(!scale) {
o << " Bin : " << i << ", " << xaxis_.GetBinMin(i)
<< ", " << count_[i] << endl;
Calcolo L
} else {
int j=(int)(count_[i]*scale);
Scrivo nella stringa come se
stringstream s;
s<< setw(6) << xaxis_.GetBinMin(i)<<"|";
fosse uno stream il valore del
s<< left << string(j,'-') << "|";
bin
o << s.str() << endl;
}
}
Creo una string di L caratteri ‘-’
e la scrivo nella stringstream
Modificatori di I/O.
setw(int):fissa la largezza di campo
295
F.S. Cafagna, Linguaggi di programmazione avanzati: C++ , XXIII ciclo
left: allinea a sinistra
Esercizio
Aggiungendo delle opzioni per selezionare il PLOT o il print del
BIN content, la class definition diventa:
#ifndef HIST_H
#define HIST_H
#include <vector>
#include <string>
#include <sstream>
#include <algorithm>
#include <iostream>
#include <iomanip>
#include "axis.h"
// Getters
int GetEntries() const { return entries_; }
int GetNbin() const { return xaxis_.GetBin(); }
double GetXmax() const { return xaxis_.GetMax(); }
double GetXmin() const { return xaxis_.GetMin(); }
const char * GetTitle() const { return title_.c_str(); }
const char * GetATitle() const { return xaxis_.GetTitle(); }
// Setters
void SetNbin( const int i ) { xaxis_.SetBin(i); }
void SetXmax( const double i ) { xaxis_.SetMax(i); }
void SetXmin( const double i ) { xaxis_.SetMin(i); }
void SetTitle( const char *c ) { title_=c; }
void SetATitle( const char *c) { xaxis_.SetTitle(c); }
using std::vector;
using std::string;
using std::stringstream;
using std::right;
using std::fixed;
using std::endl;
using std::cout;
using std::left;
using std::setw;
using std::ostream;
void Print( ostream & o=cout, opt op=PLOT ) const;
// scale, must be equal to MAXCHAR / MAXELE
void PrintBin( const int i, ostream &o=cout, double scale=0. ) const;
#define MAXCHAR 60.
typedef vector <int> vint;
class hist {
public:
enum opt {ALL,BIN,PLOT};
hist(double xmax=1., double xmin=0., int bin=100,
const char *t="none", const char *at="none"):
xaxis_(xmax,xmin,bin,at), count_(bin+2), entries_(0), title_(t) {};
private:
vint count_;
axis xaxis_;
int entries_;
string title_;
};
#endif // HIST_H
hist.h
bool Fill(double x);
F.S. Cafagna, Linguaggi di programmazione avanzati: C++ , XXIII ciclo
296
Esercizio
#include "hist.h"
void hist::Print( ostream & o, opt op) const {
int maxele=*(max_element( count_.begin()+1,
count_.end()-1));
o << " Histo : " << title_ << endl;
o << " Max value : " << maxele << endl;
o << " Underflow : " << *count_.begin()
<< ", Overflow : " << *count_.end() << endl;
switch(op) {
case BIN:
for( int i=0; i<(count_.size()); PrintBin(i++,o) );
break;
case PLOT:
for( int i=1; i<(count_.size()-1); PrintBin(i++, o,
MAXCHAR/maxele ) );
break;
case ALL:
for( int i=0; i<(count_.size()); PrintBin(i++,o) );
for( int i=1; i<(count_.size()-1); PrintBin(i++, o,
MAXCHAR/maxele ) );
break;
}
}
// scale, must be equal to MAXCHAR / MAXELE
void hist::PrintBin( const int i, ostream &o, double scale )
const {
if(!scale) {
o << " Bin : " << i << ", " << xaxis_.GetBinMin(i)
<< ", " << count_[i] << endl;
} else {
int j=(int)(count_[i]*scale);
stringstream s;
s<< setw(6) << xaxis_.GetBinMin(i)<<"|";
s<< left << string(j,'-') << "|";
o << s.str() << endl;
}
}
bool hist::Fill(double x){ int i=xaxis_.Bin(x);
if(i<=count_.size()) {
count_[i]++;
entries_++;
return true;
}
return false;
}
hist.cpp
F.S. Cafagna, Linguaggi di programmazione avanzati: C++ , XXIII ciclo
297
Esercizio
A questo punto non ci resta che usare queste classi
#include "hist.h"
#include "gaussrnd.h"
#include <fstream>
using std::ofstream;
int main() {
hist t(3.,-3., 150, "grandom", "count") ;
gaussrnd g(12345);
for(int j=0; j<500000; j++, t.Fill(g.Grnd()));
ofstream f("test_gauss.dat");
t.Print();
t.Print(f);
return 0;
}
test_hist.cpp
F.S. Cafagna, Linguaggi di programmazione avanzati: C++ , XXIII ciclo
298
Esercizio
Non dimentichiamo il Makefile:
CC=g++
test_hist: hist.o axis.o test_hist.o gaussrnd.o
F.S. Cafagna, Linguaggi di programmazione avanzati: C++ , XXIII ciclo
299
Esercizi
Provate a:
Correggere la classe axis. Che succede se calcolo
Bin(min_) ? Viene ritornato il numero di bin corretto ?
Provare ad “estendere” l’utilizzo delle classi axis e
hist, anche ai double utilizzando il template
Provare a scrivere un generatore di numeri random
distribuiti secondo una esponenziale
−y
(hint: y ( x) =− ln( x), p( y )dy = e dy )
Provate a scrivere una classe base rndgen, da cui
fare derivare le classi: gaussrnd, exprnd
Provate a riscrivere il main in modo che utilizzi solo la
classe base dei generatori random e che possiate
scegliere il generatore via cin
F.S. Cafagna, Linguaggi di programmazione avanzati: C++ , XXIII ciclo
300