如何从rand()获取特定范围的数字?

srand(time(null)); printf("%d", rand()); 

给出一个高范围的随机数(0-32000ish),但我只需要大约0-63或0-127,但我不知道该怎么去做。 任何帮助?

 rand() % (max_number + 1 - minimum_number) + minimum_number 

所以,对于0-65:

 rand() % (65 + 1 - 0) + 0 

(显然你可以把0closures,但是为了完整性,这是在那里)。

请注意,这会使随机性略有偏差,但如果您没有做特别敏感的事情,可能不会有任何担心。

在这里检查

http://c-faq.com/lib/randrange.html

对于这些技术中的任何一种,如果需要,可以直接移动范围; 可以用类似的东西生成[M,N]范围内的数字

 M + rand() / (RAND_MAX / (N - M + 1) + 1) 

以其他海报所宣称的结果模数来给你一些几乎是随机的东西,但并不完全如此。

考虑这个极端的例子,假设你想模拟硬币抛掷,返回0或1.你可能会这样做:

 isHeads = ( rand() % 2 ) == 1; 

看起来无害,对吗? 假设RAND_MAX只有3,当然这要高得多,但是这里要指出的是,当你使用一个不能均匀分配RAND_MAX的模数时,会有一个偏差。 如果你想要高质量的随机数字,你会有一个问题。

考虑我的例子。 可能的结果是:

 rand() freq. rand() % 2 0 1/3 0 1 1/3 1 2 1/3 0 

因此,“尾巴”会发生两次“头”!

阿特伍德先生在这个编码恐怖条款中讨论这个问题

正如其他人所指出的那样,简单地使用模数将会扭曲单个数字的概率,因此较小的数字是首选的。

Java的java.util.Random类中使用了一个非常巧妙的解决scheme:

 public int nextInt(int n) { if (n <= 0) throw new IllegalArgumentException("n must be positive"); if ((n & -n) == n) // ie, n is a power of 2 return (int)((n * (long)next(31)) >> 31); int bits, val; do { bits = next(31); val = bits % n; } while (bits - val + (n-1) < 0); return val; } 

我花了一段时间才明白它为什么起作用,我把这个作为一个练习给读者,但这是一个非常简洁的解决scheme,它将确保数字具有相同的概率。

这段代码中的重要部分是while循环的条件,它拒绝落在数字范围内的数字,否则会导致不均匀的分布。

你可以使用这个:

 int random(int min, int max){ return min + rand() / (RAND_MAX / (max - min + 1) + 1); } 

来自:

comp.lang.c常见问题列表·问题13.16

问:如何获得一定范围内的随机整数?

答:显而易见的方式,

 rand() % N /* POOR */ 

(试图从0到N-1返回数字)是不好的,因为许多随机数发生器的低阶比特是令人痛心的非随机的。 (见问题13.18)更好的方法是类似的

 (int)((double)rand() / ((double)RAND_MAX + 1) * N) 

如果你不想使用浮点,另一种方法是

 rand() / (RAND_MAX / N + 1) 

如果你只需要以1 / N的概率做一些事情,你可以使用

 if(rand() < (RAND_MAX+1u) / N) 

所有这些方法显然都需要知道RAND_MAX(ANSI定义的),并假设N比RAND_MAX小得多。 当N接近RAND_MAX时,如果随机数发生器的范围不是N的倍数(即,如果(RAND_MAX + 1)%N!= 0),所有这些方法都会崩溃:其他。 (使用浮点数没有帮助;问题是rand会返回RAND_MAX + 1个不同的值,不能总是将它们平均分配到N个桶中)。如果这是一个问题,那么可以做的唯一事情就是调用rand multiple次,丢弃某些值:

 unsigned int x = (RAND_MAX + 1u) / N; unsigned int y = x * N; unsigned int r; do { r = rand(); } while(r >= y); return r / x; 

对于这些技术中的任何一种,如果需要,可以直接移动范围; 范围[M,N]中的数字可以用类似的东西生成

 M + rand() / (RAND_MAX / (N - M + 1) + 1) 

(请注意,RAND_MAX是一个常数,告诉你C函数rand函数的固定范围是多less,你不能把RAND_MAX设置成其他的值,也不可能要求其他值的rand返回值。)

如果你从一个随机数发生器开始,它返回0到1之间的浮点数(例如问题13.15提到的PMrand的最后一个版本,或者问题13.21的 drand48),你只需要从整数0到N-1将该生成器的输出乘以N:

 (int)(drand48() * N) 

其他链接

参考文献:K&R2 Sec。 7.8.7 p。 168 PCS Sec。 11页。 172

引用自: http : //c-faq.com/lib/randrange.html

 double scale = 1.0 / ((double) RAND_MAX + 1.0); int min, max; ... rval = (int)(rand() * scale * (max - min + 1) + min); 

如果你不过分关心低位的“随机性”,只需rand()%HI_VAL。

也:

 (double)rand() / (double)RAND_MAX; // lazy way to get [0.0, 1.0) 

更新为不使用#define

 double RAND(double min, double max) { return (double)rand()/(double)RAND_MAX * (max - min) + min; } 

rand()将返回0到RAND_MAX之间的数字,至less是32767。

如果你想获得一个范围内的数字,你可以使用模数。

 int value = rand() % 66; // 0-65 

为了更准确, 请查看这篇文章 。 它讨论了为什么模数不一定好(分布差,特别是在高端),并提供了各种select。

天真的做法是:

 int myRand = rand() % 66; // for 0-65 

这可能是一个非常不均匀的分布(取决于你的最大值),但它非常接近。

要解释为什么它不是统一的,请考虑这个非常简单的例子:
假设RAND_MAX是4,你想要一个0-2的数字。 您可以得到的可能值显示在此表中:

 rand() | rand() % 3 ---------+------------ 0 | 0 1 | 1 2 | 2 3 | 0 

看到问题? 如果您的最大值不是RAND_MAX的均数,那么您将更有可能select小的值。 但是,由于RAND_MAX通常是32767,所以偏差很可能足够小,以便达到大多数目的。

有很多方法可以解决这个问题。 请参阅这里了解Java的Random如何处理它的解释。

我认为以下是半正确的。 我已经触摸C了一段时间了。这个想法是使用除法,因为模数不总是给出随机结果。 我加了1到RAND_MAX,因为有很多可能的值来自rand,包括0.而且由于范围也是0,所以我也加了1。 我认为math是正确安排避免整math问题。

 #define MK_DIVISOR(max) ((int)((unsigned int)RAND_MAX+1/(max+1))) num = rand()/MK_DIVISOR(65); 

如果你关心你的随机数的质量,不要使用rand()

使用一些像http://en.wikipedia.org/wiki/Mersenne_twister其他prng或其他高质量prng之一在那里;

那么就用模量去吧。

或者你可以使用这个:

 rand() / RAND_MAX * 65 

但我不确定这是所有答案中最随机或最快的答案。