根本没有随意 - 替代品?

时间:2011-10-17 08:46:17

标签: c++ random srand

我正在玩弄数组,填充伪随机数,找到最小值和最大值以及它们的索引和出现次数,我注意到了一些奇怪的事情 - 当使用srand播种时间时最小值​​和最大值的数量事件始终相等。这对我来说似乎不太随意。

是否有另一种方法可以获得不同数量的最小值和最大值值,就像人们对随机数的预期一样?

这是我的代码(我正在学习,所以它可能是凌乱和低效的,欢迎推荐)

#include <cstdlib>
#include <iostream>
#include <time.h>

using namespace std;

void findExtremes( const int[], int); 

int main()
{
    const int lenght = 2000; //define lenght

    int array1[lenght];

    srand(time(0)); 

    for ( int i = 0; i < lenght; i++) //populate array with random numbers and print them out
    {
        array1[i] = rand() % 3000;
        cout << "Index " << i << " = " << array1[i] << endl;
    }

    findExtremes(array1, lenght);   // call fn

    return 0;
}

void findExtremes( const int array[], int size)
{
     int maxV, minV, maxI, minI;
     maxV = array[0];
     minV = array[0];
     minI = 0;
     maxI = 0;

     for ( int i = 1; i < size; i++)
     {
         if ( array[i] > maxV)
            {
                maxV = array[i];
                maxI = i;
            }
         if ( array[i] < minV)
            {
                minV = array[i];
                minI = i;
            }
     }

     //find the number of occurances for min and max values

     int minOcc = 0;
     int maxOcc = 0;

     for ( int i = 1; i < size; i++)
     {
             if (array[i] == minV)
                 minOcc++;
             if (array[i] == minV)
                 maxOcc++;
     }

     //output

     cout << "\nMinmim value is index " << minI << " with value " << minV << " and " << minOcc << " occurances" << endl;
     cout << "\nMaxium value is index " << maxI << " with value " << maxV << " and " << maxOcc << " occurances" << endl << "\n";  
}

6 个答案:

答案 0 :(得分:3)

首先,它们实际上是随机数,而不是随机数。在任何情况下,它可能是一个真正随机的序列具有您正在看到的确切属性:-)序列1,1,1,1,1同样可能发生在真正的随机集合中,与5,2,4,2,99一样多。

如果你想要一个“更随机”的随机序列,我就不会使用C库附带的正常序列(除非这些库是由了解随机性的人编写的) - 你应该研究像Mersenne Twister这样的东西,使用/dev/random(如果在Linux下)等等。

您可能还想查看代码片段。

if (array[i] == minV)
    minOcc++;
if (array[i] == minV)
    maxOcc++;

我认为最后if应该与maxV而不是minV进行比较。否则,您的最小和最大计数将不同。

当我进行更改(并将% 3000更改为% 30,以获得一系列重复项)时,我看到:

Minmim value is index 112 with value 0 and 65 occurances
Maxium value is index 24 with value 29 and 58 occurances

而且,就这个问题而言,这并不重要,你可能想要在某种程度上清理你的拼写:

  • lenght - &gt; length
  • minmum - &gt; minimum
  • maxium - &gt; maximum
  • occurances - &gt; occurrences

答案 1 :(得分:1)

我对物理进行数值模拟,我的小组使用GSL library

#include <gsl/gsl_rng.h>
#include <gsl/gsl_randist.h>

class Random
{
private:
    gsl_rng* r; //!< Pointer to the gsl rng
public:
    //! Constructor: uses argument as the seed
    Random(long unsigned int seed);

    long int R(int N);
    long double R();
    long double gaussianR(long double sigma);
};

inline Random::Random(long unsigned int s)
{
    r = gsl_rng_alloc( gsl_rng_taus );
    gsl_rng_set(r, s); //seed to use to the pseudo-aleatory number generator.
}

// a uniform number between 0 and N-1
inline long int Random::R(int N)
{
    return gsl_rng_uniform_int (r, N);
}

// a uniform number between 0 and 1
inline long double Random::R()
{
    return gsl_rng_uniform_pos( r );
}

// a gaussian distribution with sigma
inline long double Random::gaussianR(long double sigma)
{
    return gsl_ran_gaussian(r, sigma);
}

你必须用旗子编译它: OTHER_LDFLAGS = -lgsl -lm -lgslcblas

并添加includes和libs(这适用于fink安装案例):

HEADER_SEARCH_PATHS = / sw / include LIBRARY_SEARCH_PATHS = / sw / lib

希望这有帮助。

答案 2 :(得分:0)

  

绅士:注意

     

是的!这个答案是“老”。在c ++ 11时代,一定要使用c ++ 11 <random>。但是,不要在事实之后几年内投下这个问题,因为你认为“ Ew 每个人知道 rand()是邪恶的!” 。事实上,事实并非如此。它只是有限的,并且非常容易使用。 但是 - 作为一个历史事实,它作为一个API存在,仍然有助于记录如何使用它更好。我没有删除这个答案。

     

原始答案:

     

请阅读

http://eternallyconfuzzled.com/arts/jsw_art_rand.aspx

值得注意的是,不要写rand() % 3000。写

 int r = rand() / ( RAND_MAX / 3000 + 1 );

事实上,随机应该是均匀分布的,这意味着当样本数量足够大时(对于初学者而言,大于域的大小),下限和上限确实会有接近100%的发生几率。 / p>

这就是真正的随机性(尝试不使用蒙特卡罗算法 - 你会非常不满意)

答案 3 :(得分:0)

您可以使用C ++ 11中包含的新random库,也可以使用它基于的Boost :: Random库。

答案 4 :(得分:0)

我认为问题在于您的初始陈述是错误的。 代码每次都提供不同的数字。我尝试了未经修改的代码,结果如下:

Minmim value is index 1194 with value 0 and 1 occurances
Maxium value is index 1264 with value 2995 and 1 occurances

Minmim value is index 1958 with value 1 and 1 occurances
Maxium value is index 1510 with value 2991 and 1 occurances

...

但是,代码中有两个错误:

  • 在第二个for循环中,你应该从i = 0开始。
  • 您应该在同一循环中与maxV而不是minV进行比较。

关于随机数生成:

  • 当播种相同的号码时,系列的rand()calles应返回相同的数字。 rand()不是随机数,而是伪随机数。 rand()应该有这种方式,因为当使用相同的种子启动时,模拟将输出相同的结果。这是一个非常好的财产。
  • 您使用当前时间播种,这是正常的,因此rand()每次都应返回不同系列的数字(至少多次不调用时)一秒)。播种对我来说很好看。事实上它与here提供的示例非常相似。
  • 样本大小为2000,生成的数字范围为3000.这意味着最小大小和最大大小不可能始终相同。如果样本量为百万,则概率很高2999应该是最多运行中的最大数量。

答案 5 :(得分:0)

伪随机数发生器(PRNG)的行为完全正常。

事实上,如果你从rand()中抽取足够的数字,你将永远得到相同的极值,因为它是均匀分布的。

在您的情况下,问题是:您是否需要其他行为?你不应该像@sehe建议的那样扑向真随机数。这可能毫无用处,甚至在处理蒙特卡罗算法的随机模拟时也存在问题。想象一下,您想要根据随机数调试代码片段,或者您的同事打算检查您的结果:如果您无法重现相同的随机序列,您会怎么做? < / p>

这就是为什么PRNG足够并且在您不需要加密安全随机数时通常首选的原因之一。