如何在C

时间:2016-10-03 19:46:52

标签: c random

我已经阅读了很多关于这个主题的帖子:

How does rand() work? Does it have certain tendencies? Is there something better to use?

How does the random number generator work in C

这就是我得到的:

1)xn + 1取决于xn,即生成的先前随机数。

2)不建议在程序中多次初始化种子。

3)使用rand()%2随机生成0或1是一种不好的做法。

我的问题是:

1)是否还有其他我想错过的库来生成一个完全随机的数字(0或1),而不依赖于以前的输出?

2)如果还有其他工作要使用内置的rand()函数来满足要求吗?

3)在程序中多次初始化种子有什么副作用?

代码段:

srand(time(NULL));
d1=rand()%2;
d2=rand()%2;

这里我的目的是使d1和d2完全相互独立。

我最初的想法是这样做:

srand(time(NULL));
d1=rand()%2;
srand(time(NULL));
d2=rand()%2;

但正如我之前提到的基于其他帖子,我认为这是一种不好的做法?

那么,任何人都可以回答上述问题吗?如果我完全错过了一件明显的事情,我道歉。

3 个答案:

答案 0 :(得分:2)

  
      
  1. 是否还有其他任何我想错过的库可以生成0到1之间的完全随机数,而不依赖于以前的输出?
  2.   

不在标准C库中。还有很多其他库可以生成“更好”的伪随机数。

  
      
  1. 如果还有其他工作要使用内置的rand()函数来满足要求吗?
  2.   

rand的大多数标准库实现产生随机数序列,其中低阶位具有短序列和/或不像人们希望的那样彼此独立。高阶位通常更好地分布。因此,使用标准库rand函数生成随机单个位(0或1)的更好方法是:

(rand() > RAND_MAX / 2)

或使用内部位:

(rand() & 0x400U != 0)

这些将与大多数标准库rand实现产生合理不相关的序列,并且不会产生比检查低位更多的计算开销。如果这对你不够好,你可能想研究其他伪随机数生成器。

所有这些(包括rand() % 2)都假设RAND_MAX是奇数,这几乎总是如此。 (如果RAND_MAX是偶数,则会有奇数个可能的值,任何将奇数个可能值划分为两个阵营的方式都必须略有偏差。)

  
      
  1. 在程序中多次初始化种子有什么副作用?
  2.   

您应该将随机数生成器视为在播种后生成“非常随机”的数字,随着您连续生成新的随机数,质量会提高。请记住,如果使用某种种子为随机数生成器播种,则下次使用相同种子为生成器播种时,将获得完全相同的序列。 (由于time()返回几秒钟,连续两次连续呼叫通常会产生完全相同的数字,或者偶尔会产生两个连续的数字。但绝对不是两个随机不相关的数字。)

因此,重播的副作用是你得到的随机数较少,而且可能与你上一次重新接种时的数字完全相同。

答案 1 :(得分:1)

  

1)是否有其他我想念的图书馆   生成0到1之间的完全随机数而不依赖   在以前的输出?

这个子问题对于Stack Overflow来说是偏离主题的,但是我会指出POSIX和BSD系统有一个名为random()的替代随机数生成器函数,如果你正在为这样一个编程,你可以考虑这个函数平台(例如Linux,OS X)。

  

2)如果还有其他工作使用内置的rand()函数   满足要求?

传统计算机(与量子计算机相对)是确定性计算机。他们不能做真正的随机性。每个完全编程的“随机数生成器”实际上是 psuedo - 随机数生成器。它们生成完全确定的序列,但来自给定调用集的值以与目标概率分布(通常是均匀分布)大致一致的方式分布在生成器的范围内。

某些操作系统支持生成依赖于比计算序列更混乱且更难预测的数字。例如,他们可以从鼠标移动,CPU温度变化或其他此类来源收集信息,以产生更客观随机(但仍然确定)的数字。例如,Linux有这样的驱动程序,通常作为特殊文件/dev/random公开。这些问题是它们具有有限的熵存储,因此不能以持续的高速率提供数字。但是,如果您只需要几个随机数,那么这可能是一个合适的来源。

  

3)多次初始化种子的副作用是什么?   一个程序?

     

代码段:

srand(time(NULL));
d1=rand()%2;
d2=rand()%2;
     

这里我的目的是使d1和d2完全独立于每个   其他

     

我最初的想法是这样做:

srand(time(NULL));
d1=rand()%2;
srand(time(NULL));
d2=rand()%2;
     

但正如我之前提到的基于其他帖子,这是一个   我想是不好的做法?

如果您希望d1d2有50%的不同概率,那确实很糟糕。 time()返回自纪元以来的数量,因此很有可能在两次如此接近调用时返回相同的值。伪随机数的序列完全由种子决定(这是一个特征,而不是一个bug),当您为PRNG播种时,重新启动序列。即使你使用更高分辨率的时钟使种子更容易出现差异,你也不会以这种方式逃避相关性;你只需要为你改变生成数字的函数。结果对输出分布没有相同的保证。

此外,执行rand() % 2时,只使用它为您生成的大约log2(RAND_MAX)+ 1位中的一位。在PRNG的整个期间,您可以期望该位使每个值具有相同的次数,但是在较窄的范围内,您有时可能会看到一些相关性。

最后,您对两个随机数完全独立的要求可能有点过分。通常,一次调用的伪随机结果与先前调用的结果没有明显的相关性就足够了。即使尽可能每次调用只使用一位代码片段,您也可以使用第一个代码片段实现这一点。但是,如果您更喜欢使用更多的位,那么您可以根据rand()返回的值中设置的位数的奇偶校验位置选择数字。

答案 2 :(得分:0)

使用此

(double)rand() / (double)RAND_MAX
  

完全随机数.....不依赖于以前的输出?

实际上,计算机无法生成完全随机的数字。必须有一些依赖。但是对于几乎所有实际用途,您都可以使用rand()

  

多次初始化种子的副作用

无副作用。但这意味着你完全无效使用rand()。如果您每次都重新启动种子,则随机数更多地取决于时间(和处理器)。

  

使用内置rand()函数的任何其他工作

你可以这样写:

#include<stdio.h>
#include<stdlib.h>
#include<time.h>

int main(int argc,char *argv[])
{
    srand(time(NULL));
    printf("%lf\n",(double)rand()/(double)RAND_MAX);
    printf("%lf\n",(double)rand()/(double)RAND_MAX);
}

如果你想生成 0或1 ,我认为使用rand()%2是完全正常的,因为偶数的概率与奇数概率相同(概率)对于无偏的随机数发生器,所有数字都是相等的。)