而不是随机的——选择
srand not random at all - alternatives?
我在玩弄数组,用伪随机数填充,找到最小值和最大值及其索引和出现次数,我注意到一些奇怪的东西- 当使用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";
}
首先,它们实际上是伪随机数,而不是随机数。在任何情况下,可能是一个真正的随机序列具有你所看到的确切属性:-)序列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
->length
. -
minmum
->minimum
-
maxium
->maximum
-
occurances
->occurrences
我对物理进行数值模拟,我的小组使用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);
}
你必须用flags来编译:OTHER_LDFLAGS = -lgsl -lm -lgslcblas
和添加包含和库(这是fink安装情况):
HEADER_SEARCH_PATHS =/sw/includeLIBRARY_SEARCH_PATHS =/sw/lib
希望这对你有帮助。
您可以使用c++ 11中包含的新的random
库,或者您可以使用它所基于的Boost::Random库。
您的伪随机数生成器(PRNG)的行为完全正常。
事实上,如果你从rand()
中抽取足够的数字,你将总是得到相同的极值,因为它是均匀分布的。
在您的情况下,问题是:您是否需要另一个行为?你不应该像@sehe建议的那样突然攻击真实随机数。这可能是无用的,甚至在处理随机模拟时,蒙特卡罗算法是有问题的。想象一下,您想要调试一个基于随机数的代码片段,或者您的同事想要检查您的结果:如果您无法重现相同的随机序列,您该怎么办?
这就是为什么当你不需要加密安全的随机数时,prng是足够的,并且通常是首选的原因之一。
我认为问题是你最初的陈述是错误的。代码是每次提供不同的数字。我尝试了未修改的代码,结果如下:
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。这意味着最小尺寸和最大尺寸不可能总是相同的。如果样本量是100万,那么2999很有可能是大多数运行中最大的数字。
Gentlepeople:注意
是的!这个答案是"老"的。在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%的机会发生。
这就是真正的随机(尝试在没有它的情况下做蒙特卡罗算法-你会非常不高兴)
- 从C++数组中选择一个随机元素
- 通过选择 2 个随机值来优化表达式
- 如何更改此notify_one以便它选择一个随机线程
- 选择随机字符串数组的排序
- C++ 在运行时选择一个随机对象
- 如何从文件夹树中快速选择随机文件?
- 从长(且合理)稀疏向量中选择随机元素的最有效方法是什么?
- 如何在QT中设置样式表以选择假发背景的随机图像
- 随机选择 2 个不在范围内的整数
- 在C++中随机选择子类
- 如何从图形的邻接列表表示中随机选择边缘
- 回溯到sudoku求解每次选择随机单元和随机值的逻辑
- 如何有效地从std::集中选择随机元素
- 为多映射中的特定键选择随机元素
- 用于选择随机子集的通用算法实现
- 在unordered_map中选择随机元素
- 使用c++从.dat文件中选择“随机行”
- 从结构向量中选择随机结构
- 如何使用向量中的信息填充数组并从数组中选择随机项
- 有没有比这更好的方法从可变大小的数组中选择随机元素