头文件:
/*
* Copyright (c) 2008-2011 Zhang Ming (M. Zhang), zmjerry@163.com
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 2 or any later version.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details. A copy of the GNU General Public License is available at:
* http://www.fsf.org/licensing/licenses
*/
/*****************************************************************************
* random.h
*
* Random Number Generator.
*
* The class Random can generate an "long int" random number. The default
* initial state is set to 1, of cause it can be set to any integer through
* routine "seed(int)".
*
* Based on the "Random" class, we can generate some usually used distributed
* pseudorandom number or pseudorandom sequence. These distributions include:
* Uniform Normal Exponential Rayleigh Poisson
* Bernoulli
*
* Zhang Ming, 2010-10, Xi'an Jiaotong University.
*****************************************************************************/
#ifndef RANDOM_H
#define RANDOM_H
#include <vector.h>
namespace splab
{
class Random
{
public:
explicit Random( long int initValue=1 );
~Random();
void seed( long int value );
long int random();
long int getM() const;
private:
static const long int A = 48271;
static const long int M = 2147483647;
static const long int Q = 44488;
static const long int R = 3399;
long int state;
};
template<typename Type> Type randu( int, const Type&, const Type& );
template<typename Type> Type randn( int, const Type&, const Type& );
template<typename Type> Type rande( int, const Type& );
template<typename Type> Type randr( int, const Type& );
template<typename Type> int randp( int, const Type& );
template<typename Type> int randb( int, const Type& );
template<typename Type> Vector<Type> randu( int, const Type&,
const Type&, int );
template<typename Type> Vector<Type> randn( int, const Type&,
const Type&, int );
template<typename Type> Vector<Type> rande( int, const Type&, int );
template<typename Type> Vector<Type> randr( int, const Type&, int );
template<typename Type> Vector<int> randp( int, const Type&, int );
template<typename Type> Vector<int> randb( int, const Type&, int );
#include <random-impl.h>
}
// namespace splab
#endif
// RANDOM_H
实现文件:
/*
* Copyright (c) 2008-2011 Zhang Ming (M. Zhang), zmjerry@163.com
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 2 or any later version.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details. A copy of the GNU General Public License is available at:
* http://www.fsf.org/licensing/licenses
*/
/*****************************************************************************
* random-impl.h
*
* Implementation for Random class and random generator.
*
* Zhang Ming, 2010-10, Xi'an Jiaotong University.
*****************************************************************************/
/**
* constructors and destructor
*/
Random::Random( long int initValue )
{
if( initValue < 0 )
initValue += M;
state = initValue;
if( state == 0 )
state = 1;
}
Random::~Random()
{
}
/**
* Set the internal state.
*/
inline void Random::seed( long int value )
{
state = value;
}
/**
* Return a pseudorandom int, and then change the internal state.
*/
long int Random::random()
{
long int tmpState = A*( state%Q ) - R*( state/Q );
if( tmpState >= 0 )
state = tmpState;
else
state = tmpState + M;
return state;
}
/**
* Return M.
*/
inline long int Random::getM() const
{
return M;
}
/**
* Return an Uniform[low, high] distributed pseudorandom number.
*/
template <typename Type>
Type randu( int seed, const Type &low, const Type &high )
{
static Random rg( seed );
long double u_0_1 = rg.random() / (long double)rg.getM();
return low + Type( u_0_1*(high-low) );
}
/**
* Return a Normal~(mu, sigma) distributed pseudorandom number.
*/
template <typename Type>
Type randn( int seed, const Type &mu, const Type &sigma )
{
static Random rg( seed );
long double u_0_1 = 0.0;
for( int i=0; i<12; ++i )
u_0_1 += rg.random()/(long double)rg.getM();
u_0_1 -= 6.0;
return Type( sigma*u_0_1 + mu );
}
/**
* Return a Exponential~(beta) distributed pseudorandom number.
*/
template <typename Type>
Type rande( int seed, const Type &beta )
{
static Random rg( seed );
long double u_0_1 = rg.random()/(long double)rg.getM();
return Type( -beta*log(u_0_1) );
}
/**
* Return a Rayleigh~(sigma) distributed pseudorandom number.
*/
template <typename Type>
Type randr( int seed, const Type &sigma )
{
static Random rg( seed );
long double u_0_1 = rg.random() / (long double)rg.getM();
return Type( sigma * sqrt(-2.0*log(u_0_1)) );
}
/**
* Return a Poisson~(lambda) distributed pseudorandom number.
*/
template <typename Type>
int randp( int seed, const Type &lambda )
{
static Random rg( seed );
long double u_0_1 = 0.0,
q = exp(-lambda),
p = 1.0;
int k = 0;
while( p >= q )
{
u_0_1 = rg.random()/(long double)rg.getM();
p *= u_0_1;
k++;
}
return k-1;
}
/**
* Return a Bernoulli~(p) distributed pseudorandom number.
*/
template <typename Type>
int randb( int seed, const Type &p )
{
static Random rg( seed );
long double u_0_1 = rg.random() / (long double)rg.getM();
return ( Type(u_0_1) <= p ) ? 1 : 0;
}
/**
* Return an Uniform[low, high] distributed pseudorandom sequence of size N.
*/
template <typename Type>
Vector<Type> randu( int seed, const Type &low, const Type &high, int N )
{
long double u_0_1 = 0.0;
Random rg( seed );
Vector<Type> rs(N);
for( int i=0; i<N; ++i )
{
u_0_1 = rg.random() / (long double)rg.getM();
rs[i] = low + Type( u_0_1*(high-low) );
}
return rs;
}
/**
* Return an Normal~(mu, sigma) distributed pseudorandom sequence of size N.
*/
template <typename Type>
Vector<Type> randn( int seed, const Type &mu, const Type &sigma, int N )
{
long double u_0_1;
Random rg( seed );
Vector<Type> rs(N);
for( int i=0; i<N; ++i )
{
u_0_1 = 0.0;
for( int j=0; j<12; ++j )
u_0_1 += rg.random()/(long double)rg.getM();
u_0_1 -= 6.0;
rs[i] = Type(sigma*u_0_1) + mu;
}
return rs;
}
/**
* Return an Exponential~(beta) distributed pseudorandom sequence of size N.
*/
template <typename Type>
Vector<Type> rande( int seed, const Type &beta, int N )
{
long double u_0_1 = 0.0;
Random rg( seed );
Vector<Type> rs(N);
for( int i=0; i<N; ++i )
{
u_0_1 = rg.random() / (long double)rg.getM();
rs[i] = Type( -beta*log(u_0_1) );
}
return rs;
}
/**
* Return an Rayleigh~(sigma) distributed pseudorandom sequence of size N.
*/
template <typename Type>
Vector<Type> randr( int seed, const Type &sigma, int N )
{
long double u_0_1 = 0.0;
Random rg( seed );
Vector<Type> rs(N);
for( int i=0; i<N; ++i )
{
u_0_1 = rg.random() / (long double)rg.getM();
rs[i] = Type( sigma * sqrt(-2.0*log(u_0_1)) );
}
return rs;
}
/**
* Return a Poisson~(lambda) distributed pseudorandom sequence of size N.
*/
template <typename Type>
Vector<int> randp( int seed, const Type &lambda, int N )
{
Random rg( seed );
Vector<int> rs(N);
long double u_0_1 = 0.0,
q = exp(-lambda),
p = 1.0;
int k = 0;
for( int i=0; i<N; ++i )
{
k = 0;
p = 1.0;
while( p >= q )
{
u_0_1 = rg.random()/(long double)rg.getM();
p *= u_0_1;
k++;
}
rs[i] = k-1;
}
return rs;
}
/**
* Return a Bernoulli~(p) distributed pseudorandom sequence of size N.
*/
template <typename Type>
Vector<int> randb( int seed, const Type &p, int N )
{
long double u_0_1 = 0.0;
Random rg( seed );
Vector<int> rs(N);
for( int i=0; i<N; ++i )
{
u_0_1 = rg.random() / (long double)rg.getM();
rs[i] = ( Type(u_0_1) <= p ) ? 1 : 0;
}
return rs;
}
测试代码:
/*****************************************************************************
* random_test.cpp
*
* Random number generator testing.
*
* Zhang Ming, 2010-10, Xi'an Jiaotong University.
*****************************************************************************/
#include <iostream>
#include <iomanip>
#include <random.h>
#include <statistics.h>
using namespace std;
using namespace splab;
typedef double Type;
const int N = 100;
int main()
{
int seed = 37;
int low = 0, high = 100;
Type mu = 0.0, sigma = 1.0;
Type beta = 2.0;
Type lambda = 4.0;
Type p = 0.5;
Vector<Type> rs(N);
Vector<int> irs(N);
Vector<double> tmp(N);
// Random rand(seed);
// cout << "Random Number Generator:" << endl;
// for( int i=0; i<N; ++i )
// {
// cout << rand.random() << "\t";
// if( !((i+1)%4) )
// cout << endl;
// }
// cout << endl << endl;
cout << "Uniform distribution: U ~ ( " << low << ", " << high << " )" << endl;
for( int i=0; i<N; ++i )
cout << randu( seed, low, high ) << "\t";
cout << endl;
irs = randu( seed, low, high, N );
cout << "mean (theoretical generated): "
<< mean(irs) << "\t" << (high-low)/2 << endl;
cout << "variance (theoretical generated): "
<< var(irs) << "\t" << (high-low)*(high-low)/12
<< endl << endl << endl;
cout << "Normal distribution: N ~ ( " << mu << ", " << sigma << " )" << endl;
cout << setiosflags(ios::fixed) << setprecision(4);
for( int i=0; i<N; ++i )
cout << randn( seed, mu, sigma ) << "\t\t";
cout << endl;
rs = randn( seed, mu, sigma, N );
cout << "mean (theoretical generated): "
<< mean(rs) << "\t" << mu << endl;
cout << "variance (theoretical generated): "
<< var(rs) << "\t" << sigma*sigma
<< endl << endl << endl;
cout << "Exponential distribution: E ~ ( " << beta << " )" << endl;
cout << setiosflags(ios::fixed) << setprecision(4);
for( int i=0; i<N; ++i )
cout << rande( seed, beta ) << "\t\t";
cout << endl;
rs = rande( seed, beta, N );
cout << "mean (theoretical generated): "
<< mean(rs) << "\t" << beta << endl;
cout << "variance (theoretical generated): "
<< var(rs) << "\t" << beta*beta
<< endl << endl << endl;
cout << "Rayleigh distribution: R ~ ( " << sigma << " )" << endl;
cout << setiosflags(ios::fixed) << setprecision(4);
for( int i=0; i<N; ++i )
cout << randr( seed, sigma ) << "\t\t";
cout << endl;
rs = randr( seed, sigma, N );
cout << "mean (theoretical generated): "
<< mean(rs) << "\t" << sigma*sqrt(PI/2.0) << endl;
cout << "variance (theoretical generated): "
<< var(rs) << "\t" << (2-PI/2)*sigma*sigma
<< endl << endl << endl;
cout << "Poisson distribution: B ~ ( " << p << " )" << endl;
for( int i=0; i<N; ++i )
cout << randp( seed, lambda ) << "\t\t";
cout << endl;
irs = randp( seed, lambda, N );
for( int i=0; i<N; ++i )
tmp[i] = irs[i];
cout << "mean (theoretical generated): "
<< mean(tmp) << "\t" << lambda << endl;
cout << "variance (theoretical generated): "
<< var(tmp) << "\t" << lambda
<< endl << endl << endl;
cout << "Bernoulli distribution: B ~ ( " << p << " )" << endl;
for( int i=0; i<N; ++i )
cout << randb( seed, p ) << "\t\t";
cout << endl;
irs = randb( seed, p, N );
for( int i=0; i<N; ++i )
tmp[i] = irs[i];
cout << "mean (theoretical generated): "
<< mean(tmp) << "\t" << p << endl;
cout << "variance (theoretical generated): "
<< var(tmp) << "\t" << p*(1-p)
<< endl << endl;
return 0;
}
运行结果:
Uniform distribution: U ~ ( 0, 100 )
0 14 25 98 81 1 5 72 72 50
31 73 54 95 90 93 43 81 86 76
99 76 28 16 35 57 9 74 55 87
64 34 41 5 63 22 49 13 91 46
55 99 18 26 21 59 65 9 27 87
10 70 81 42 35 62 23 24 62 71
35 6 84 38 86 82 76 45 34 38
65 29 42 94 45 46 80 42 6 11
46 65 20 21 2 88 71 74 58 43
56 94 17 5 32 0 66 54 97 40
mean (theoretical generated): 49 50
variance (theoretical generated): 840 833
Normal distribution: N ~ ( 0, 1 )
-0.7148 2.4179 -0.4947 -0.4264 0.0118
0.2321 -0.7548 -0.5397 -0.6533 -1.2043
1.8746 0.7539 0.0210 0.3340 0.2786
-1.8528 -0.7200 1.1448 -0.7554 -1.0937
0.1583 -2.9330 0.3818 -0.0193 -1.3456
1.4424 1.8424 -0.6886 1.6361 0.9801
1.2555 0.1753 1.6852 0.4694 -0.2241
-2.2454 -1.3620 -0.2316 -2.3769 1.0066
-0.3988 0.5761 -0.2895 -0.2019 -0.6050
-0.4084 -0.4072 -1.2768 0.9203 -0.0252
-0.5463 -0.3924 -1.2157 -0.9195 -0.2086
0.0866 0.3005 0.2995 0.8217 1.5764
0.5863 2.6818 0.4002 -0.3112 -1.5317
-1.0913 0.4349 0.7805 1.3383 0.4580
-0.8948 0.1357 -0.1333 0.7235 0.7452
-0.2743 1.0441 -0.5881 -0.1807 1.8741
0.4193 -0.1397 0.7841 0.8995 1.7939
1.0729 -1.0523 -1.0604 0.1780 -1.8157
0.8338 -0.2278 0.7157 0.8513 0.7649
0.4494 -1.6238 0.5206 -0.0174 0.1020
mean (theoretical generated): 0.0480 0.0000
variance (theoretical generated): 1.0853 1.0000
Exponential distribution: E ~ ( 2.0000 )
14.1841 3.8456 2.7722 0.0209 0.4107
7.9776 5.8336 0.6396 0.6362 1.3468
2.3214 0.6173 1.2231 0.0943 0.2085
0.1379 1.6627 0.4015 0.2789 0.5368
0.0145 0.5387 2.5359 3.6533 2.0613
1.1008 4.7209 0.5873 1.1839 0.2580
0.8894 2.1468 1.7691 5.9504 0.9212
3.0099 1.3934 3.9596 0.1688 1.5344
1.1923 0.0128 3.3930 2.6764 3.0453
1.0373 0.8570 4.6297 2.5929 0.2703
4.4738 0.6858 0.4023 1.6962 2.0739
0.9469 2.8776 2.8258 0.9276 0.6701
2.0931 5.4628 0.3361 1.8864 0.2925
0.3967 0.5345 1.5645 2.1240 1.9347
0.8492 2.4460 1.7180 0.1191 1.5695
1.5185 0.4214 1.7257 5.5630 4.2447
1.5262 0.8318 3.2001 3.0868 7.5201
0.2372 0.6579 0.5884 1.0777 1.6624
1.1570 0.1181 3.4733 5.8509 2.2530
9.7065 0.8140 1.1978 0.0423 1.8098
mean (theoretical generated): 2.0445 2.0000
variance (theoretical generated): 5.0310 4.0000
Rayleigh distribution: R ~ ( 1.0000 )
3.7662 1.9610 1.6650 0.1445 0.6409
2.8245 2.4153 0.7997 0.7976 1.1605
1.5236 0.7857 1.1060 0.3070 0.4566
0.3714 1.2895 0.6336 0.5281 0.7326
0.1203 0.7340 1.5924 1.9114 1.4357
1.0492 2.1728 0.7664 1.0881 0.5080
0.9431 1.4652 1.3301 2.4393 0.9598
1.7349 1.1804 1.9899 0.4108 1.2387
1.0919 0.1133 1.8420 1.6360 1.7451
1.0185 0.9257 2.1517 1.6103 0.5199
2.1151 0.8281 0.6343 1.3024 1.4401
0.9731 1.6964 1.6810 0.9631 0.8186
1.4468 2.3373 0.5798 1.3735 0.5408
0.6299 0.7311 1.2508 1.4574 1.3909
0.9215 1.5640 1.3107 0.3452 1.2528
1.2323 0.6492 1.3137 2.3586 2.0603
1.2354 0.9120 1.7889 1.7569 2.7423
0.4871 0.8111 0.7671 1.0381 1.2893
1.0756 0.3436 1.8637 2.4189 1.5010
3.1155 0.9022 1.0944 0.2056 1.3453
mean (theoretical generated): 1.2553 1.2533
variance (theoretical generated): 0.4735 0.4292
Poisson distribution: B ~ ( 0.5000 )
0 4 3 11 2
5 2 3 5 3
3 5 3 7 5
3 3 2 5 1
0 6 1 4 3
4 6 9 4 5
6 5 4 5 4
4 3 4 3 3
1 8 4 6 3
4 1 5 2 3
6 2 3 1 2
7 3 5 4 3
1 3 6 7 9
1 1 2 5 7
6 7 8 5 3
6 7 7 1 5
1 6 2 3 1
3 3 2 4 4
5 2 1 3 3
1 3 4 6 5
mean (theoretical generated): 3.9000 4.0000
variance (theoretical generated): 4.6566 4.0000
Bernoulli distribution: B ~ ( 0.5000 )
1 1 1 0 0
1 1 0 0 0
1 0 0 0 0
0 1 0 0 0
0 0 1 1 1
0 1 0 0 0
0 1 1 1 0
1 1 1 0 1
0 0 1 1 1
0 0 1 1 0
1 0 0 1 1
0 1 1 0 0
1 1 0 1 0
0 0 1 1 1
0 1 1 0 1
1 0 1 1 1
1 0 1 1 1
0 0 0 0 1
0 0 1 1 1
1 0 0 0 1
mean (theoretical generated): 0.5100 0.5000
variance (theoretical generated): 0.2524 0.2500
Process returned 0 (0x0) execution time : 0.203 s
Press any key to continue.