0

我正在玩弄数组,填充伪随机数,找到最小值和最大值以及它们的索引和出现次数,我注意到一些奇怪的事情 -当使用 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";  
}
4

6 回答 6

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++;

我认为 lastif应该与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-> length
  • minmum->minimum
  • maxium->maximum
  • occurances->occurrences
于 2011-10-17T08:50:16.207 回答
1

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

#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

并添加包含和库(这是用于 fink 安装案例):

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

希望这可以帮助。

于 2011-10-17T09:10:04.523 回答
0

绅士们:注意

是的!这个答案是“旧的”。而在 c++11 时代,一定要使用 c++11 <random>。但是不要在事实发生多年后对这个问题投反对票,因为您认为“每个人都知道 rand()是邪恶的!”。事实上,事实并非如此。它只是有限的,而且很容易不当使用。但是- 作为一个历史事实,它作为 API 存在,并且记录如何更好地使用它仍然很有用。我没有删除这个答案是有原因的。

原答案:


请阅读

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

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

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

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

这就是真正的随机性(尝试在没有它的情况下进行蒙特卡洛算法 - 你会非常不开心)

于 2011-10-17T08:51:45.823 回答
0

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

于 2011-10-17T08:53:29.193 回答
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() 调用应该返回相同的数字。rand() 不是用于随机数,而是用于伪随机数。rand() 应该采用这种方式,因为例如,当使用相同的种子启动时,模拟将输出相同的结果。这是一个非常好的财产。
  • 使用当前时间播种它,这是可以的,因此 rand()每次都应该返回不同的数字系列(至少在不被调用多次时)。播种对我来说看起来不错。它实际上与此处提供的示例非常相似。
  • 样本大小为 2000,生成数字的范围为 3000。这意味着最小大小和最大大小不可能始终相同。如果样本量为一百万,则很有可能 2999 应该是最多运行中的最大数字。
于 2011-10-17T09:00:48.523 回答
0

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

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

就您而言,问题是:您是否需要另一种行为?你不应该像@sehe 建议的那样猛扑真随机数。在处理随机模拟时,这可能是无用的,甚至是有问题的,蒙特卡洛算法就是这样。想象一下,你想调试一个基于随机数的代码片段,或者你的同事打算检查你的结果:如果你不能重现相同的随机序列,你会怎么做?

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

于 2011-10-17T09:06:29.873 回答