rand()在循环条件下的行为

时间:2014-10-09 22:51:25

标签: c++ loops random iteration

我试图更好地理解包含某种rand()作为其结束条件的循环的行为。请考虑以下示例:

for(int i=0; i < rand()%6+10; i++) { do something }

在这种情况下,循环将迭代10到15次。 我的问题是:终止值是否会被评估一次,然后重复用于其余的迭代?或者每次迭代都会重新评估它?

另外,这被认为是不好的做法吗?

2 个答案:

答案 0 :(得分:4)

在每次迭代之前完全评估条件。 (想一想:编译器如何知道每次要评估哪些部分,以及你不知道哪些部分?)

是否不好的做法取决于具体情况。如果终止条件可能在循环期间发生变化,则有意义。如果你想循环一个随机的次数,那么你应该预先评估终止价值,否则你会得到一个与你想象的不同的随机分布。

如果您在每次迭代时评估rand(),则满足终止条件的几率将根据i的值更改每次迭代,并且您会发现{{1}的某些终止值与均匀分布相比过度代表。话虽如此,在你的情况下,即使你提前评估,分布也不会是统一的,因为(1)i不能保证产生统一分布的值,并且我知道, (2)取随机函数的模数,其范围不能被模数整除,将使分布偏斜。随机函数的范围越大,给定特定模数的偏差越小,但它仍然存在。

答案 1 :(得分:1)

C ++标准说for语句:

for ( for-init-statement conditionopt ; expressionopt ) statement

相当于:

{ for-init-statement while ( condition) { statement expression ; } }

  

[注意:因此第一个语句指定了初始化   环;条件(6.4)指定在每个之前进行的测试   迭代,[...]

所以是的,每次迭代都会重新评估条件。

至于是否使用rand()是不好的做法...... rand()函数依赖于库和平台。在linux上,您可以通过man 3 rand找到文档。例如,online man page说:

  

请勿在可移植的应用程序中使用此功能   需要良好的随机性。

cppreference's opinion on std::rand

  

无法保证随机序列的质量   产生的。在过去,rand()的一些实现已经有了   随机性,分布和时期的严重缺陷   产生的序列(在一个众所周知的例子中,简单地说是低阶位   在电话之间交替1到0之间。

     

rand()不建议用于严重的随机数生成需求,   像密码学。建议使用C ++ 11的random number generation facilities   替换rand()(自C ++ 11起)

如果您想要了解如何使用这些C ++ 11功能,请参阅Random number generation in C++11, how to generate, how do they work?

有关rand()的各种用法及其原因的分析,请参阅Julienne Walker's article

例如:

1 int r = rand() % N;
     

要改为添加下限并将范围设置为[M..N],可能会这样做   这样:

1 int r = M + rand() % ( N - M );
     

任何执行此操作的人都会得到一个看似随机的序列   并为他们聪明的解决方案工作而感到激动。不幸的是,这个   不起作用。第一种解决方案仅在N均分时才有效   进入RAND_MAX。第二种解决方案并不是更好。原因是   因为以这种方式强制范围消除了任何机会   均匀分布。现在,如果您不关心,这是可以的   有些数字比其他数字更可能,但要正确,你   必须与分发合作而不是破坏它。