我正在玩弄数组,填充伪随机数,找到最小值和最大值以及它们的索引和出现次数,我注意到了一些奇怪的事情 - 当使用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";
}
答案 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
...
但是,代码中有两个错误:
关于随机数生成:
答案 5 :(得分:0)
伪随机数发生器(PRNG)的行为完全正常。
事实上,如果你从rand()
中抽取足够的数字,你将永远得到相同的极值,因为它是均匀分布的。
在您的情况下,问题是:您是否需要其他行为?你不应该像@sehe建议的那样扑向真随机数。这可能毫无用处,甚至在处理蒙特卡罗算法的随机模拟时也存在问题。想象一下,您想要根据随机数调试代码片段,或者您的同事打算检查您的结果:如果您无法重现相同的随机序列,您会怎么做? < / p>
这就是为什么PRNG足够并且在您不需要加密安全随机数时通常首选的原因之一。