C中重复且可预测的RNG值
我试图在C语言中生成10000个随机数,但在使用伪RNG获得随机甚至随机结果时遇到困难。我用了一种我认为应该创造一致性的方法来使用模,它确实做到了,但是当在另一个调用RNG(4)的函数的循环中运行时,结果相当于0,0,0,0,0,0,0,0,1,1,1,1,1,2,2,2,2,2,3,3,3,3,3等 任何使其接近1,3,2,0,2,3,1,0,0,3,2,0,1等的方法都将不胜感激 谢谢大家!C中重复且可预测的RNG值,c,C,我试图在C语言中生成10000个随机数,但在使用伪RNG获得随机甚至随机结果时遇到困难。我用了一种我认为应该创造一致性的方法来使用模,它确实做到了,但是当在另一个调用RNG(4)的函数的循环中运行时,结果相当于0,0,0,0,0,0,0,0,1,1,1,1,1,2,2,2,2,2,3,3,3,3,3等 任何使其接近1,3,2,0,2,3,1,0,0,3,2,0,1等的方法都将不胜感激 谢谢大家! 编辑:谢谢大家的回复!将播种移动到调用RNG的函数的开头,现在一切都很好 不要每次要生成号码时都调用
编辑:谢谢大家的回复!将播种移动到调用RNG的函数的开头,现在一切都很好 不要每次要生成号码时都调用
srand
srand
初始化伪随机数生成器,并打算在程序开始时或要重置生成器时仅调用一次。通过每次重置它,您将强制rand
在时钟上每秒钟内每次调用它时生成相同的号码
不要使用x%n
将数字减少到所需的范围。众所周知,rand
的旧实现糟糕透顶,并且具有低位模式。相反,使用x/((RAND\u MAX+1u)/n)
代码int range=RAND\u MAX-(RAND\u MAX%n)代码>有缺陷。假设n
为4,RAND_MAX
为7,表示RAND
返回0到7。此代码将range
设置为4,然后将设置为while(x>range)x=rand()代码>丢弃5、6和7,而保留4。这里有两个错误:代码保留了5个值0、1、2、3和4,这与所需的4范围不匹配(不是4的倍数),并且不必要地丢弃了值。如果我们保持4、5、6和7,我们会有一场比赛。您可以使用:
unsigned range = (RAND_MAX + 1u) - ((RAND_MAX + 1u) % n);
以及:
如果你使用C++,切换到使用。如果您使用的是C,请在实现中检查
rand
的质量,或者切换到另一个生成器,例如POSIXsrandom
和random不要在每次生成数字时调用srand
srand
初始化伪随机数生成器,并打算在程序开始时或要重置生成器时仅调用一次。通过每次重置它,您将强制rand
在时钟上每秒钟内每次调用它时生成相同的号码
不要使用x%n
将数字减少到所需的范围。众所周知,rand
的旧实现糟糕透顶,并且具有低位模式。相反,使用x/((RAND\u MAX+1u)/n)
代码int range=RAND\u MAX-(RAND\u MAX%n)代码>有缺陷。假设n
为4,RAND_MAX
为7,表示RAND
返回0到7。此代码将range
设置为4,然后将设置为while(x>range)x=rand()代码>丢弃5、6和7,而保留4。这里有两个错误:代码保留了5个值0、1、2、3和4,这与所需的4范围不匹配(不是4的倍数),并且不必要地丢弃了值。如果我们保持4、5、6和7,我们会有一场比赛。您可以使用:
unsigned range = (RAND_MAX + 1u) - ((RAND_MAX + 1u) % n);
以及:
如果你使用C++,切换到使用。如果您使用的是C,请在实现中检查
rand
的质量,或者切换到另一个生成器,如POSIXsrandom
和random如其他地方所述,对重复数字的修复是将调用移动到srand(时间(NULL))
在该函数之外,每个程序在开始时只调用一次
至于为什么会出现重复的数字:该函数每秒被调用几次。每次函数在给定的秒内执行时,time(NULL)
返回相同的数字,该代码使用该数字为随机数生成器设定种子
从特定种子生成的随机数序列总是相同的。此代码从该序列中获取第一个数字,该数字在1秒内始终不变,直到time(NULL)
返回一个新值。如其他地方所述,重复数字的修复方法是将调用移到该函数之外的srand(time(NULL))
,并在每个程序开始时仅调用一次
至于为什么会出现重复的数字:该函数每秒被调用几次。每次函数在给定的秒内执行时,time(NULL)
返回相同的数字,该代码使用该数字为随机数生成器设定种子
从特定种子生成的随机数序列总是相同的。此代码从该序列中获取第一个数字,该数字在1秒内始终不变,直到time(NULL)
返回一个新值。1。选择是使用C
还是C++
。2.如果您选择了C++
,我知道每次调用RNG
,您都在使用srand
重置种子。停止在每个循环中重置srand()
。如果您想要一个可重复的伪随机数序列,请使用常量调用srand()
(一次),而不是使用时间(NULL)
,它的设计目的是在每次运行时为您提供一个新序列。或者根本不调用所有的srand()
,这相当于调用srand(1)
.1。选择是使用C
还是C++
。2.如果您选择了C++
,我知道每次调用RNG
,您都在使用srand
重置种子。停止在每个循环中重置srand()
。如果您想要一个可重复的伪随机数序列,请使用常量调用srand()
(一次),而不是使用时间(NULL)
,它的设计目的是在每次运行时为您提供一个新序列。或者根本不使用所有的srand()
,这是等效的
while (x >= range) x = rand();