如何在C中随机生成0或1

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

rand()如何工作? 它有一定的倾向吗? 有没有比这更好用的东西?

随机数生成器如何在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; 

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

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

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

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

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

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

 (rand() > RAND_MAX / 2) 

或使用内部位:

 (rand() & 0x400U != 0) 

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

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

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

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

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

1)是否有其他库我错过了看看在0和1之间生成一个完全随机的数字,而不依赖于以前的输出?

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

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

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

某些操作系统支持生成依赖于比计算序列更混乱且更难预测的数字。 例如,他们可以从鼠标移动,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; 

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

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

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

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

用这个

 (double)rand() / (double)RAND_MAX 

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

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

不止一次初始化种子的副作用

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

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

你可以写这样的东西:

 #include #include #include 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是完全正常的,因为偶数的概率与奇数的概率相同(所有数的概率对于无偏随机数是相等的发电机)。