(转)C ++ 中产生随机数

        最近在写一个产生随机数的程序时遇到了一个比较尴尬的事情:感觉C++中好像没有产生随机数的类。在网上百度之,才发现跟着自己想的一样。大多数都是使用srand()函数与rand()函数。但是这两个函数令人不是很放心:1、rand()函数产的数据是伪随机的(当然计算机上产生的随机数都是伪随机的,但是这个比较明显,如果srand()函数的种子相同的话,结果就相同。如果要连续产生比较好的随机,那么种子的选择就非常关键了)。1、rand()函数产生的伪随机数的范围是有限的0~0x7fff。如果需要的范围比这个小倒是好办,求余即可。如果比这个范围大的话。那么又要费神想这个扩大这个随机数的范围了。附上一篇讲随机数函数使用的文章(转载):

     C++中产生随机数种子对于初学者一直都很困惑.大家知道,在C中有专门的srand(N)函数可以轻松实现这一功能,然而在C++中则要复杂一些.下面是笔者学习的一点心得,希望对大家能有所帮助.(这里我们依然要借助C标准库中的rand()函数)

  函数说明:

 

应用举例:
1):


 

2):


以下源码来自crafty19.3,最强的源码开放的chess程序。注释很清楚,无需多言。
问:
1.Knuth的书中是怎么讲的?该书我无缘拜读。
2.static const unsigned long x[55],这里取55个随机数的理由是什么?
3.能否比较全面地讲讲随机数产生的一些算法或理论,或推荐一些参考资料?

对于初学者来说,只需熟练掌握1)种用法,更深层次的随着水平的提升自然会有所领悟.

另:


一、C++中不能使用random()函数      random函数不是ANSI C标准,不能在gcc,vc等编译器下编译通过。可改用C++下的rand函数来实现。      1、C++标准函数库提供一随机数生成器rand,返回0-RAND_MAX之间均匀分布的伪随机整数。 RAND_MAX必须至少为32767。rand()函数不接受参数,默认以1为种子(即起始值)。随机数生成器总是以相同的种子开始,所以形成的伪随机数列也相同,失去了随机意义。(但这样便于程序调试)
      2、C++中另一函数srand(),可以指定不同的数(无符号整数变元)为种子。但是如果种子相同,伪随机数列也相同。一个办法是让用户输入种子,但是仍然不理想。
      3、比较理想的是用变化的数,比如时间来作为随机数生成器的种子。 time的值每时每刻都不同。所以种子不同,所以,产生的随机数也不同。
// C++随机函数(VC program)

二、rand()的用法  
      rand()不需要参数,它会返回一个从0到最大随机数的任意整数,最大随机数的大小通常是固定的一个大整数。这样,如果你要产生0~10的10个整数,可以表达为:
  int N = rand() % 11;
      这样,N的值就是一个0~10的随机数,如果要产生1~10,则是这样:
  int N = 1 + rand() % 11;
  总结来说,可以表示为:
  a + rand() % n
      其中的a是起始值,n是整数的范围。   a + rand() % (b-a+1) 就表示 a~b之间的一个随机数若要0~1的小数,则可以先取得0~10的整数,然后均除以10即可得到随机到十分位的10个随机小数,若要得到随机到百分位的随机小数,则需要先得到0~100的10个整数,然后均除以100,其它情况依
此类推。
      通常rand()产生的随机数在每次运行的时候都是与上一次相同的,这是有意这样设计的,是为了便于程序的调试。若要产生每次不同的随机数,可以使用srand( seed )函数进行随机化,随着seed的不同,就能够产生不同的随机数。
      如大家所说,还可以包含time.h头文件,然后使用srand(time(0))来使用当前时间使随机数发生器随机化,这样就可以保证每两次运行时可以得到不同的随机数序列(只要两次运行的间隔超过1秒)。

### C++ 中生成随机数的方法 C++ 提供了多种方式来生成随机数,这些方法既可以通过传统的 `rand` 函数实现,也可以通过现代标准(如 C++11 及其后续版本)引入的更强大的随机数库完成。 #### 使用传统 `rand()` 方法 在早期的标准中,C 和 C++ 均提供了基于 `rand()` 的简单随机数生成功能。为了确保每次运行程序时产生的序列不同,通常会使用 `srand(seed)` 设置种子值[^2]。 以下是示例代码: ```cpp #include <iostream> #include <cstdlib> // rand(), srand() #include <ctime> // time() int main() { std::srand(std::time(0)); // 使用当前时间作为种子 for (int i = 0; i < 5; ++i) { std::cout << std::rand() % 100 << ' '; // 输出范围 [0, 99] } return 0; } ``` 这种方法虽然简单易用,但在某些情况下可能无法满足高质量随机性的需求。 --- #### 使用 C++11 随机数引擎和分布 自 C++11 起,标准库新增了一套功能强大且灵活的随机数工具集,位于 `<random>` 头文件中。这套工具主要包括 **随机数引擎** 和 **分布类**[^4]。 ##### 示例:使用默认随机数引擎 (`default_random_engine`) 下面是一个利用 `default_random_engine` 和均匀整数分布的例子: ```cpp #include <iostream> #include <random> int main() { std::default_random_engine engine{std::random_device{}()}; std::uniform_int_distribution<int> dist(1, 100); // 定义范围 [1, 100] for (int i = 0; i < 5; ++i) { std::cout << dist(engine) << ' '; } return 0; } ``` 此代码片段展示了如何创建一个随机数引擎并结合分布类生成指定范围内的伪随机数。 --- ##### 示例:使用 Mersenne Twister 引擎 (`mt19937`) Mersenne Twister 是一种高效的随机数算法,在许多场景下表现优异。以下是如何配置它的例子: ```cpp #include <iostream> #include <random> int main() { std::mt19937 engine{std::random_device{}()}; std::normal_distribution<double> dist(5.0, 2.0); // 正态分布,均值为 5.0,方差为 2.0 for (int i = 0; i < 5; ++i) { std::cout << dist(engine) << ' '; } return 0; } ``` 这里选择了正态分布作为演示的一部分,说明除了离散分布外,还可以处理连续概率分布。 --- #### 结合 `std::random_device` 对于更高安全性和不可预测性的情况,可以考虑使用 `std::random_device` 来初始化随机数引擎。尽管它本身仅用于获取少量非确定性数据,但它非常适合充当种子源[^3]。 示例如下: ```cpp #include <iostream> #include <random> int main() { std::random_device rd; std::mt19937 engine(rd()); std::bernoulli_distribution dist(0.8); for (int i = 0; i < 5; ++i) { std::cout << (dist(engine) ? "true" : "false") << ' '; } return 0; } ``` 上述代码实现了布尔类型的伯努利试验模拟。 --- ### 总结 以上分别介绍了三种主要途径——经典 `rand()`、现代化的 C++11 随机数框架以及增强版的安全机制。开发者可以根据项目的需求选取最合适的方案。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值