生成随机位-C rand()中缺少随机性

生成随机位-C rand()中缺少随机性,c,random,C,Random,我正在使用rand()生成0或1(rand()%2)。我正在使用当前时间(srand(time(NULL))对其进行种子设定 经过多次调试,我意识到,rand()不会连续16次或更多次返回偶数(奇数) 这是一个已知的问题吗?C有更好的PRNG吗 我使用Visual Studio 2010在Windows 7上运行。rand()random()稍微好一点(有时),但drand48()及其系列要好得多 如果您需要更好的,请查看mersene twister或其他PRNG库。或者查看/dev/rand

我正在使用
rand()
生成0或1(
rand()%2
)。我正在使用当前时间(
srand(time(NULL))
对其进行种子设定

经过多次调试,我意识到,
rand()
不会连续16次或更多次返回偶数(奇数)

这是一个已知的问题吗?C有更好的PRNG吗

我使用Visual Studio 2010在Windows 7上运行。

rand()
random()
稍微好一点(有时),但
drand48()
及其系列要好得多


如果您需要更好的,请查看mersene twister或其他PRNG库。或者查看/dev/random,如果可以提供足够的数据满足您的需要。

请尝试
rand()>(rand_MAX/2)
而不是使用
rand()%2
。您只能假设
rand()
在间隔
[0,rand\u MAX]
上是一致的

编辑:这是沙巴兹在评论中提出的,我只是在发布了这个答案后才注意到

Edit:ArjunShankar用我之前的话对我说:“rand()只指定在区间[0,rand_MAX]上是一致的。”

根据C99标准:

rand函数计算范围在0到0之间的伪随机整数序列 兰德·马克斯


从技术上讲,未规定均匀性(或均匀分布),但实际标准用于实施常用PRNG(如Mersenne捻线机)。这是为了允许程序员轻松创建具有非均匀分布的自定义PRNG。如果没有此属性,程序员将被迫从头开始实现自定义PRNG。

我建议使用更好的RNG。您在Windows上运行,因此可以使用:这是一个使用Windows加密RNG的Microsoft扩展。

好的,您可以使用Mersenne Twister或Well的算法。井的代码在这里(我没有足够的声誉)

兰德从不在一行中返回16次或以上的偶数(奇数)
-好吧。。。你测试了多少次?小于
2^16
次?连续获得16个赔率的概率为
(1/2)^16
。这相当低…大约10亿倍,足以让16个偶数(奇数)数字粗略显示128倍(如果我的计算正确的话)。在一些(较旧的)rand实现中,低阶位的随机性比高阶位小。尝试
(rand()>rand_MAX/2?1:0)
模偏差可能是个问题。请参阅“rand()仅指定为在间隔[0,rand_MAX]上是一致的”-没有说明任何关于一致性的内容。还有其他来源吗?好的,我也查了C99。不能保证整个范围内的一致性。当然,这并不意味着你的解决方案是错误的。很可能这确实实现了OP测试的序列类型。简洁的答案+1因为我想让OP试一试。还有一个原因是,
rand
价格非常便宜。谷歌建议不要。windows上还提供了其他随机数生成函数,如CryptGenRandom,或者您可以使用外部库,如MT-
rand()
历史上存在过问题。有关数学知识,请参见乔治·马萨格里亚的。您的C库可能仍然存在此问题,也可能不存在此问题。对于任何需要严重随机性的情况,Mersenne Twister(由@eviotto提供的链接)或另一种现代pRNG都是最好的。加密RNG速度慢,而且对于大多数应用程序来说都是多余的。它是加密的(与PRNG相比,速度非常非常慢),因为比特实际上是随机的,来自外部事件,而不是伪随机的。这也使得调试变得更加困难。@sfstewman我建议权衡问题的作者来评估和决定。你的答案虽然可以解决OP的问题,但也会产生新的问题。加密RNG并不适合一次生成数十亿个随机比特。OP代码的模2会将每次调用
rand_s
时除一个位外的所有位都丢弃,这会使情况更加复杂。这是31或63位的纯熵消失了。您至少应该警告OP,并建议他们可以使用
rand_s
中的每一位,而不仅仅是LSB。