在C中生成之间的随机数?

我已经看到很多关于这个特定主题的问题,但没有一个对我有任何答案,所以我想问这个问题。

我想在[-1,1]之间生成一个随机数。 我怎么能这样做?

使用-1+2*((float)rand())/RAND_MAX

rand()生成[0,RAND_MAX]范围内的整数,因此, ((float)rand())/RAND_MAX返回[0,1]的浮点数。 我们通过将它添加到-1得到[-1,1]的随机数。

编辑:(添加评论部分的相关部分)

关于这种方法的局限性:

((float)rand())/RAND_MAX返回一个百分比(从0到1的分数)。 因此,由于-1到1之间的范围是2个整数,我将该分数乘以2,然后将其加到所需的最小数字-1。 这也会告诉您随机数的质量,因为您只有RAND_MAX唯一的随机数。

如果你拥有的只是标准C库,那么其他人的答案是明智的。 如果您有POSIXfunction,请考虑使用drand48()系列函数。 特别是:

 #define _XOPEN_SOURCE 600 /* Request non-standard functions */ #include  double f = +1.0 - 2.0 * drand48(); double g = -1.0 + 2.0 * drand48(); 

请注意,手册说:

drand48()和erand48()函数应返回非负的,双精度的浮点值,均匀分布在区间[0.0,1.0]上。

如果你严格需要[-1.0,+1.0] (而不是[-1.0,+1.0) ),那么你将面临一个非常微妙的问题,如何扩展范围。

drand48()函数比rand()的典型实现提供了更多的随机性。 但是,如果您需要加密随机性,则这些都不合适; 你需要寻找’密码强PRNG’(PRNG =伪随机数发生器)。

我不久前有一个类似的问题,并认为直接生成小数部分可能更有效。 我做了一些搜索并遇到了一个有趣的快速浮点rand,它不使用浮点除法或乘法,或者int-> float cast可以通过对float的内部表示的一些深入了解来完成:

 float sfrand( void ) { unsigned int a=(rand()<<16)|rand(); //we use the bottom 23 bits of the int, so one //16 bit rand() won't cut it. a=(a&0x007fffff) | 0x40000000; return( *((float*)&a) - 3.0f ); } 

第一部分从[2 ^ 1,2 ^ 2)生成随机浮点数,减去3,你有[-1,1]。 对于某些应用程序/开发人员而言,这当然可能过于贴心,但这正是我所寻求的。 这种机制适用于2宽度范围的任何范围。

首先,你需要C库函数rand() 。 这是在stdlib.h头文件中,所以你应该把:

 #include  

靠近代码的开头。 rand()将生成一个介于0和RAND_MAX之间的随机整数,因此除以RAND_MAX / 2将得到一个介于0和2之间的数字。 减去一个,你的目标范围是-1到1。

但是,如果你只是做int n = rand() / (RAND_MAX / 2)你会发现你没有得到你期望的答案。 这是因为rand()RAND_MAX / 2都是整数,因此使用整数运算。 为了防止这种情况发生,有些人使用浮动投射,但我建议通过乘以1.0避免强制转换。

您还应该使用srand()函数为随机数生成器播种。 为了每次获得不同的结果,人们通常通过srand(time(0))基于时钟时间为发生器播种。

所以,总的来说我们有:

 #include  srand(time(0); double r = 1.0 * rand() / (RAND_MAX / 2) - 1; 

虽然在许多情况下接受的答案很好,但它会省去“每隔一个数字”,因为它将一系列已离散的值扩展为2以覆盖[-1,1]间隔。 以类似的方式,如果你有一个随机数生成器,可以生成[0,10]的整数,你想生成[0,20],简单地乘以2将跨越范围,但不能覆盖范围(它会遗漏所有奇数)。

它可能具有足够精细的颗粒以满足您的需求,但确实存在这种缺点,这在许多应用中可能具有统计意义(并且有害) – 尤其是蒙特卡罗模拟和对初始条件具有敏感依赖性的系统。

能够生成从-1到1(包括-1)的任何可表示的浮点数的方法应该依赖于生成序列a1.a2 a3 a4 a5 …直到浮点精度的极限,这是唯一的方法在该范围内生成任何可能的浮动。 (即遵循实数的定义)

来自“C标准库”

int rand(void) – 返回0RAND_MAX范围内的伪随机数

RAND_MAXrand()返回的最大值。

所以:

rand()将返回0RAND_MAX范围内的伪随机数

rand() / RANDMAX将返回01范围内的伪随机数

2*( rand() / RANDMAX )将返回02范围内的伪随机数

2*( rand() / RANDMAX ) -1将返回-11范围内的伪随机数

正如其他人已经指出的那样,任何简单地将’rand()’函数范围从[0,RAND_MAX]转换为所需[-1,+ 1]的尝试都会产生一个随机数生成器,它只能生成一组离散的浮动点值。 对于浮点生成器,在某些应用程序中,这些值的密度可能不足(如果实现定义的RAND_MAX值不够大)。 如果这是一个问题,可以通过使用两个或多个’rand()’调用而不是一个来指数地增加上述密度。

例如,通过将两个连续调用的结果组合到’rand()’,可以在[0,(RAND_MAX + 1)^ 2 – 1]范围内获得伪随机数。

 #define RAND_MAX2 ((RAND_MAX + 1ul) * (RAND_MAX + 1) - 1) unsigned long r2 = (unsigned long) rand() * (RAND_MAX + 1) + rand(); 

然后使用相同的方法将其转换为[-1,+ 1]范围内的浮点数

 double dr2 = r2 * 2.0 / RAND_MAX2 - 1; 

通过使用这种方法,可以根据需要建立尽可能多的’rand()’调用,当然要注意整数溢出。

作为旁注,这种组合连续’rand()’调用的方法不会产生非常高质量的伪随机数生成器,但它可以很好地用于许多目的。