了解Visual C++的 rand() 函数的算法
Understanding the algorithm of Visual C++'s rand() function
在C/c++中,当我们想要得到一个随机整数时,通常使用rand()
和srand()
。但当我试图自己重写它时,我发现很难理解这个算法。这个函数只用几行就很容易写出来,但是这个公式却容易被误解。
主公式:
ptd->_holdrand = ptd->_holdrand * 214013L + 2531011L;
原始代码:
void __cdecl srand (unsigned int seed)
{
_getptd()->_holdrand = (unsigned long)seed;
}
int __cdecl rand (void)
{
_ptiddata ptd = _getptd();
return ( ((ptd->_holdrand = ptd->_holdrand * 214013L + 2531011L) >> 16) & 0x7fff );
}
这只是模运算。您正在乘以并添加一个以2^32取模的数字(例如),并返回上面的16位作为您的"随机"数字。因为你是在对模数进行互质相乘和相加,这就产生了一种均匀分布的数。
仔细选择这两个数字是非常重要的。例如,如果您使用"* 4"answers"+ 8",您可能不会体验到很多随机性。
这个方案叫做线性同余。
该伪随机数生成器是一个线性同余生成器。
您可以在本月(7-2011)发表在Dr. Dobb's Journal (DDJ)上的一篇优秀文章中找到关于线性同余生成器(LCG)和其他类似家族或伪随机生成器的解释,以及关于这些特定常数的选择:快速,高质量,并行随机数生成器:比较实现。
我认为你需要在DDJ的网站(免费)注册才能阅读本文的第一部分(链接),但如果你对c++和数学感兴趣,你应该这样做…
在调用rand之前,由于srand的手册页指出"如果没有提供种子值,rand()函数将自动使用值1作为种子",那么调用rand的更好方法是首先调用srand,它将"将其参数设置为rand()返回的新伪随机整数序列的种子"。
作为一个例子,考虑以下awk, nawk, gawk代码,它在bash shell脚本中用于创建一个新的(随机)mac地址-即代码片段中引用的.genmacaddr:
enter code here
BEGIN {
n0 = "00"
srand()
n1 = sprintf("%02x", int(255 * rand()))
n2 = sprintf("%02x", int(255 * rand()))
n3 = sprintf("%02x", int(255 * rand()))
n4 = sprintf("%02x", int(255 * rand()))
n5 = sprintf("%02x", int(255 * rand()))
print n0":"n1":"n2":"n3":"n4":"n5
}
,其中bash shell脚本中的代码片段为:
enter code here
ifconfig eth0 down
newmacaddr=`nawk -f .genmacaddr -`
ifconfig eth0 hw ether $newmacaddr
ifconfig eth0 up
如果我没弄错的话,srand的种子值是从系统时钟派生出来的。
我希望这能帮助你理解一种可以工作的编码解决方案。
这是一个线性同余(如果你想深入了解这些伪随机值是如何产生的,你可以去查一下)
种子存储在_getptd()->_holdrand(以下称为holdrand)
这段代码通过执行普通的乘法和加法步骤来"工作",但随后溢出保持位得到隐含的"模量"0x100000000。
我提到这一点是因为它不是很明显,通常不被认为是好的风格。
从技术上讲,溢出整数变量会引起未定义行为,但在大多数平台上,这是可以预测的,所以微软的工程师忽略了这个问题。
- 为什么这个运算符<重载函数对 STL 算法不可见?
- STL算法函数在多个一维容器上的使用
- A*算法中魔方的启发式函数 人工智能
- 使用指针算法修改函数中的 2D 数组
- 如何将 c++ get 函数代码转换为 opencv 算法中使用的 python
- 如何在算法中使用谓词函数find_if?
- 我们如何并行运行算法的 n 个实例并以有效的方式计算结果函数的平均值?
- 如何在复杂的算法中处理goto函数?
- 快速排序函数在快速排序算法中如何工作?
- 在 c++ 或 python 中生成一个体面的视差图以在 Raspberry Pi 上实现的最佳方法(算法或函数)是什么
- 阴算法(音高检测) - 差分函数的替代
- 算法中的排序函数返回错误
- 如何处理算法中具有不同名称成员函数的类?
- 在 stl 算法中使用函数对象
- 插入排序算法在放入函数时的行为不同
- std::bitset 哈希函数算法
- 轻量级 8 字节哈希函数算法
- C++中的合并函数算法有问题
- C++有序链表搜索函数算法逻辑
- C++sort()函数算法