如何从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
但我不确定这是所有答案中最随机或最快的答案。