随机数是编程中经常用到的操作,特别在进行初始化的时候需要赋一些随机值。C和C++中产生随机数的方法有使用rand()、srand()等,这些函数在 OpenCV中仍然可以使用。此外,OpenCV特地编写了 C++的随机效类 cV::RNG,使用起来更加方便。计算机产生的随机数都是伪随机数,是根据种子 seed 和特定算法计算出来的。所以,只要种子一定,算法一定,产生的随机数是相同。
一、产生一个随机数
1、使用种子产生一个 32 位随机整数
这种方式是直接利用构造函数RNG()和RNG(uint64 state),比如:
RNG rng((unsigned)time(NULL));
int N1 = rng;
cout << "0x" << N1 << endl;
2.产生一个均匀分布的随机数
利用成员函数 uniform实现,函数声明如下:
inline int RNG::uniform(int a, int b) { return a == b ? a : (int)(next() % (b - a) + a); }
inline float RNG::uniform(float a, float b) { return ((float)*this)*(b - a) + a; }
inline double RNG::uniform(double a, double b) { return ((double)*this)*(b - a) + a; }
返回一个[a,b)范围的均匀分布的随机数,a、b的数据类型要一致,而且必须是 int、foat、double中的一种,默认是 int。
3.产生一个高斯分布的随机数
利用成员函数 gaussian 实现,函数声明如下:
double gaussian(double sigma);
返回一个均值为0、标准差为sigma的高斯分布的随机数。如果要产生均值为λ、标准差为sigma的高斯分布的随机数,可以用λ+RNG::gaussian(sigma)来表示。
4、实例
void test01()
{
RNG rng((unsigned)time(NULL));
int N1 = rng;
cout << hex << "0x" << (int)(N1%100) << endl;
double num1 = rng.uniform(0, 1);
double num2 = rng.uniform((double)1, (double)0);
double num3 = rng.uniform(0.f, 1.f);
double num4 = rng.uniform(0., 1.);
double num5 = rng.gaussian(2);
cout << num1 << endl << num2 << endl << num3 << endl << num4 << endl << num5 << endl;
}
二、返回下一个随机数
前面一次只能返回一个随机数,实际上系统已经生成一个随机数组。如果我们要连续获得随机数,没有必要重新定义一个RNG对象,只需要取出随机数组的下一个随机数即可,所使用的成员函数是 next,函数声明如下:
inline unsigned RNG::next()
{
state = (uint64)(unsigned)state* /*CV_RNG_COEFF*/ 4164903690U + (unsigned)(state >> 32);
return (unsigned)state;
}
或者使用operator()
inline RNG::operator uchar() { return (uchar)next(); }
inline RNG::operator schar() { return (schar)next(); }
inline RNG::operator ushort() { return (ushort)next(); }
inline RNG::operator short() { return (short)next(); }
inline RNG::operator int() { return (int)next(); }
inline RNG::operator unsigned() { return next(); }
inline RNG::operator float() { return next()*2.3283064365386962890625e-10f; }
inline RNG::operator double() { unsigned t = next(); return (((uint64)t << 32) | next()) * 5.4210108624275221700372640043497e-20; }
inline unsigned RNG::operator ()(unsigned N) { return (unsigned)uniform(0,N); }
inline unsigned RNG::operator ()() { return next(); }