C语言 如何使用rand函数生成特定范围内的数字?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4270382/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 07:11:32  来源:igfitidea点击:

How to use the rand function to make numbers in a specific range?

cfunctionrandom

提问by Mr.Work

I would like to make random numbers in a specific range, like "pick a random number between 18 and 35"? How can I do that with the rand()function?

我想在特定范围内生成随机数,例如“在 18 到 35 之间选择一个随机数”?我怎样才能用这个rand()函数做到这一点?

回答by NealB

Depending on the language you are using, the built in Random number generator may already have this capability - do a bit more research.

根据您使用的语言,内置的随机数生成器可能已经具有此功能 - 多做一些研究。

Suppose that the random number generator that you have always returns numbers in some given range. Just for the sake of argument, lets say the range is 0..65536 but you want random numbers in the range Low..High, 18..35 in your example.

假设您使用的随机数生成器始终返回某个给定范围内的数字。只是为了论证起见,假设范围是 0..65536,但在您的示例中,您需要范围为 Low..High,18..35 的随机数。

The wrong way to do it would be something like:

错误的做法是这样的:

 r = (rand() % (High - Low + 1)) + Low

rand() returns a number in range 0..65536. Take the remainder after dividing by (High - Low + 1) which in this example is (35 - 18 + 1 = 18). The result is a number between 0..17. To this you add Low (18) which shifts the result, r, into the range 18..35. The range you are looking for.

rand() 返回 0..65536 范围内的数字。除以 (High - Low + 1) 后的余数,在本例中为 (35 - 18 + 1 = 18)。结果是一个介于 0..17 之间的数字。为此,您添加 Low (18),它将结果 r 移入范围 18..35。您正在寻找的范围。

Numbers generated this way do not have a uniform distribution in cases where the divisor used to obtain the remainder is not an even multiple of the upper limit returned by the rand() function. See the Fischer Yates Algorithm - Modulo Bias. To remove this bias you need to calculate the largest number that is smaller than what rand() returns but evenly divides by (High - Low + 1). In your case that is 3640 * 18 = 65520. Use this as a high range filter on the numbers returned by rand() as follows:

在用于获得余数的除数不是 rand() 函数返回的上限的偶数倍的情况下,以这种方式生成的数字没有均匀分布。请参阅Fischer Yates 算法 - 模偏差。要消除这种偏差,您需要计算小于 rand() 返回值但除以 (High - Low + 1) 的最大数字。在您的情况下,这是 3640 * 18 = 65520。将其用作 rand() 返回的数字的高范围过滤器,如下所示:

  do forever {
     r = rand()
     if r <= 65520 then {
         r = (r % (High - Low + 1)) + Low
         break
         }
     } 

Now the random numbers you generate should have the same distribution characteristics as rand().

现在您生成的随机数应该具有与 rand() 相同的分布特征。

回答by cdhowie

If this is written in C, then you are pretty close. Compiling this code:

如果这是用 C 编写的,那么您就非常接近了。编译此代码:

#include <stdio.h>
#include <stdlib.h>

int main() {
    int i;
    for (i = 0; i < 1000000; i++) {
        printf("%d\n", rand()%(35-18+1)+18);
    }
}

And running it in a pipeline produces this output:

并在管道中运行它会产生以下输出:

chris@zack:~$ gcc -o test test.c
chris@zack:~$ ./test | sort | uniq -c
  55470 18
  55334 19
  55663 20
  55463 21
  55818 22
  55564 23
  55322 24
  55886 25
  55947 26
  55554 27
  55342 28
  55526 29
  55719 30
  55435 31
  55669 32
  55818 33
  55205 34
  55265 35

The key is you forgot to add 1 -- the fencepost error.

关键是你忘了加 1 -栅栏柱错误

You can generalize this into a function:

您可以将其概括为一个函数:

int random_between(int min, int max) {
    return rand() % (max - min + 1) + min;
}

回答by HughBothwell

  1. Do you want integers-only?
  2. Do you want a uniform distribution?
  3. Do you want to include both 18 and 35 as possible values?
  4. What language would you prefer to use?
  1. 你只想要整数吗?
  2. 你想要均匀分布吗?
  3. 您想同时包含 18 和 35 作为可能的值吗?
  4. 您更喜欢使用哪种语言?

in general, if rand() returns a float value in [0.0 ... 1.0) (that is, you may get values arbitrarily close to 1.0 but not actually 1) then you will want something like

通常,如果 rand() 返回 [0.0 ... 1.0) 中的浮点值(也就是说,您可能会得到任意接近 1.0 但实际上不是 1 的值),那么您将需要类似

hi = 36
lo = 18
res = int( (hi-lo)*rand() + lo ) # returns random values in 18..35

Note that this will never actually return the hi value - therefore I have incremented it by 1 (ie, you will get all values from 18 to 35 inclusive, but never 36).

请注意,这实际上永远不会返回 hi 值 - 因此我将它增加了 1(即,您将获得从 18 到 35 的所有值,但绝不会是 36)。

Hope that helps.

希望有帮助。

回答by HughBothwell

assume rand() give you a number between 0 and 1.0

假设 rand() 给你一个 0 到 1.0 之间的数字

then use rand() * (35 - 18) + 18 to get a random number between 18 and 35.

然后使用 rand() * (35 - 18) + 18 得到一个 18 到 35 之间的随机数。

Edit: you don't need mod for this.

编辑:您不需要为此使用 mod。