VS2010中的C++产生各种“随机数”的方法(第2讲)——等概率随机量

第1讲已经详细介绍了rand()如何生成随机数的方法和基本原理。本讲我们介绍一些常见均匀随机量的生成方法:

一、闭区间[0, 1]上等概率随机小数的生成       
       x1 = rand()/(RAND_MAX+0.0) ,则x1~U[0,1]。
       如果是开区间(0, 1),则x2 = (rand()+1)/(RAND_MAX+2.0)。
       如果是半开半闭区间[0,1),则x3 = rand()/(RAND_MAX+1.0);  或者区间(0, 1],则x4 = (rand()+1)/(RAND_MAX+1.0)。
说明:1.这样生成的随机小数之间最小间隔为1.0/RAND_MAX(0至1之间最多分布RAND_MAX个不同的数);
           2.如果我们要提高均匀随机小数的分布密度,可以这样:x' = (rand()+rand()+...+rand())/(n*RAND_MAX+0.0),前面分子的rand()有n个,注意一定要离散写,因为每个rand()都是独立生成的不同随机数。

二、闭区间[float a, float b]上等概率随机浮点数的生成
      利用上面的结论,很容易知道x = x1 * float(b-a)+a ,即x~U[a,b]。
      区间为(a, b),[a, b)或(a, b]可同理推导。
说明:如果(b-a)的值很大,即a,b之间间隔很大,由于生成的所有x之间最小间隔为float(b-a)/RAND_MAX,例如如果a=0,b=RAND_MAX,则x = 0,1,2,...,RAND_MAX。所以为了提高生成的随机浮点数的分布密度,我们可以用上面的方法,即 x = x' * float(b-a)+a 。    

三、闭区间[int a, int b]上等概率随机整数的生成
      利用第一、第二的结论,生成[a, b]上等概率随机整数的公式为:k = int(x3 * float(b+1-a)+a),其中x3~U[0, 1),该方法先生成[a, b+1)上的均匀随机浮点数,然后取整,这样[a,a+1)上的浮点数取整为a,[a+1,a+2)上的浮点数取整为a+1,...,[b,b+1)上的浮点数取整为b,保证了可以得到[a, b]上所有随机整数,且取每一个的概率都相同。
      当(b-a)的值很大,即a,b之间间隔很大,同理可以用“第二”的方法提高随机分布“均匀性”!
说明:这个地方网上很多教程给的公式都是k = rand()%(b-a+1)+a,这样是不严密的!!!仅仅当(b-a)远远小于RAND_MAX时,该方法可行;但是当(b-a)比较大,例如a=0,b=20000时,这样产生的随机整数并不是“等概率”的。为什么呢?因为rand()产生的随机整数为0~RAND_MAX(=32767),整数0和20000生成的概率就不一样,rand()为0和20001时,生成的随机数都是0,但是生成整数20000却仅当rand()=20000,很明显生成0和20000的概率不相等!!!(楼主亲测)

四、三维空间沿任意方向等概率单位随机向量N = {x,y,z}的生成

float x,y,z,length;
while(1)
{
   x = -1+2*rand()/(RAND_MAX+0.0);
   y = -1+2*rand()/(RAND_MAX+0.0);
   z = -1+2*rand()/(RAND_MAX+0.0);
     if((length=x*x+y*y+z*z)<=1)  //Notice this!
             break;
}
length = sqrt(length);
float N[3] = {x/length,y/length,z/length};


 上图为空间一个包围单位球的单位立方体,生成的单位随机向量可以沿球上任何方向。如果要生成n维单位随机向量,只需将上面代码推广到n个指标!

这一讲就到此结束,第三讲讨论不等概率随机量的生成!!!

 

 

     

     

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C++,生成真随机数通常依赖于操作系统提供的API或者第三方库,因为C++标准库本身并不提供真随机数生成的功能。真随机数(true random numbers)是那些由不可预测的物理现象产生的,如硬件设备的噪声,而伪随机数(pseudo random numbers)则是算法生成的看似随机序列,虽然它们可以满足很多应用的需求,但在需要高度安全性的场合(如密码学)时,真随机数更为理想。 一种常见的方法是使用C++11引入的`<random>`库,它可以生成伪随机数,但如果你需要真随机数,你可能会考虑以下几种方案: 1. **`std::random_device`**:这是C++标准库的一部分,它试图从主机的物理特性获取随机数据,但并非真正的随机源。用法类似于这样: ```cpp std::random_device rd; std::mt19937 gen(rd()); ``` 这里`gen`是一个Mersenne Twister随机数生成器,`rd()`会填充它的种子。 2. **硬件加速的随机数生成器**:例如Intel的RDRAND指令,如果编译器支持并有相应的驱动,可以直接使用硬件提供的随机数。 3. **外部库**:有一些第三方库,如`Boost.Random`或`Expat-RNG`,提供了更复杂的真随机数生成功能,但它们可能需要额外的安装和配置。 4. **操作系统接口**:比如在Linux系统,你可以使用`/dev/urandom`文件来获取真随机数据,C++可以通过`fopen`读取。 在使用这些方法时,确保正确初始化随机数生成器并遵循安全实践,特别是在涉及敏感信息的应用。如果你需要真随机数,并且对性能有严格要求,可能还需要考虑性能和可用性的问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值