C++ 如何获得从 1 到 12 的随机值?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2254498/
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-08-27 22:44:14  来源:igfitidea点击:

C++ How I can get random value from 1 to 12?

c++random

提问by MicheleIce

How I can get in C++ random value from 1 to 12?

如何获得从 1 到 12 的 C++ 随机值?

So I will have 3, or 6, or 11?

所以我会有 3 个、6 个或 11 个?

回答by dirkgently

Use the following formula:

使用以下公式:

M + rand() / (RAND_MAX / (N - M + 1) + 1), M = 1, N = 12

and read up on this FAQ.

并阅读此常见问题解答

Edit: Most answers on this question do not take into account the fact that poor PRN generators (typically offered with the library function rand()) are not very random in the low order bits. Hence:

编辑:关于这个问题的大多数答案都没有考虑到这样一个事实,即较差的 PRN 生成器(通常与库函数一起提供rand())在低阶位中不是很随机。因此:

rand() % 12 + 1

is not good enough.

不够好。

回答by f4.

#include <iomanip>
#include <iostream>
#include <stdlib.h>
#include <time.h>

// initialize random seed
srand( time(NULL) );

// generate random number
int randomNumber = rand() % 12 + 1;

// output, as you seem to wan a '0'
cout << setfill ('0') << setw (2) << randomNumber;

to adress dirkgently's issue maybe something like that would be better?

解决直接的问题也许这样的事情会更好?

// generate random number
int randomNumber = rand()>>4; // get rid of the first 4 bits

// get the value
randomNumer = randomNumer % 12 + 1;

editafter mre and dirkgently's comments

在 mre 和 dirkgently 的评论后编辑

回答by Jerry Coffin

Is there some significance to the leading zero in this case? Do you intend for it to be octal, so the 12is really 10 (in base 10)?

在这种情况下,前导零有什么意义吗?你打算让它是八进制的,所以12真的是 10(以 10 为底)?

Getting a random number within a specified range is fairly straightforward:

获取指定范围内的随机数非常简单:

int rand_lim(int limit) {
/* return a random number between 0 and limit inclusive.
 */

    int divisor = RAND_MAX/(limit+1);
    int retval;

    do { 
        retval = rand() / divisor;
    } while (retval > limit);

    return retval;
}

(The while loop is to prevent skewed results -- some outputs happening more often than others). Skewed results are almostinevitable when/if you use division (or its remainder) directly.

(while 循环是为了防止出现偏差的结果——某些输出比其他输出发生得更频繁)。当/如果您直接使用除法(或其余数)时,偏斜的结果几乎是不可避免的。

If you want to print it out so even one-digit numbers show two digits (i.e. a leading 0), you can do something like:

如果您想将其打印出来,即使一位数字也显示两位数字(即前导 0),您可以执行以下操作:

std::cout << std::setw(2) << std::setprecision(2) << std::setfill('0') << number;

Edit: As to why this works, and why a while loop (or something similar) is needed, consider a really limited version of a generator that only produces numbers from, say, 0 to 9. Assume further that we want numbers in the range 0 to 2. We can basically arrange the numbers in a table:

编辑:至于为什么会这样,以及为什么需要 while 循环(或类似的东西),请考虑一个非常有限的生成器版本,它只生成从 0 到 9 的数字。进一步假设我们想要范围内的数字0 到 2。我们基本上可以将数字排列在一个表格中:

0 1 2
3 4 5 
6 7 8 
9

Depending on our preference we could arrange the numbers in columns instead:

根据我们的偏好,我们可以将数字排列在列中:

0 3 6  
1 4 7
2 5 8
    9

Either way, however, we end up with the one of the columns having one more number than any of the others. 10 divided by 3 will always have a remainder of 1, so no matter how we divide the numbers up, we're always going to have a remainder that makes one of the outputs more common than the others.

然而,无论哪种方式,我们最终都会得到一列的数字比其他任何一列都多。10 除以 3 的余数总是 1,因此无论我们如何将数字除以,我们总会有一个余数,使输出之一比其他输出更常见。

The basic idea of the code above is pretty simple: after getting a number and figuring where in a "table" like one above that number would land, it checks whether the number we've got is the "odd" one. If it is, another iteration of the loop is executed to obtain another number.

上面代码的基本思想非常简单:在获得一个数字并确定该数字上方的“表格”中的哪个位置后,它检查我们得到的数字是否是“奇数”。如果是,则执行循环的另一次迭代以获得另一个数字。

There are other ways this could be done. For example, you could start by computing the largest multiple of the range size that's still within the range of the random number generator, and repeatedly generate numbers until you get one smaller than that, then divide the number you receive to get it to the right range. In theory this could even be marginally more efficient (it avoids dividing the random number to get it into the right range until it gets a random number that it's going to use). In reality, the vast majority of the time, the loop will only execute one iteration anyway, so it makes very little difference what we execute inside or outside the loop.

还有其他方法可以做到这一点。例如,您可以首先计算仍在随机数生成器范围内的范围大小的最大倍数,然后重复生成数字,直到得到小于该值的一个,然后将收到的数字除以使其正确范围。从理论上讲,这甚至可以稍微提高效率(它避免将随机数划分为正确的范围,直到它获得将要使用的随机数)。实际上,在绝大多数情况下,循环只会执行一次迭代,因此我们在循环内或循环外执行的内容几乎没有区别。

回答by AndiDog

You can do this, for example:

你可以这样做,例如:

#include <cstdlib>
#include <cstdio>
#include <time.h>

int main(int argc, char **argv)
{
    srand(time(0));

    printf("Random number between 1 and 12: %d", (rand() % 12) + 1);
}

The srandfunction will seed the random number generator with the current time (in seconds) - that's the way it's usually done, but there are also more secure solutions.

srand函数将使用当前时间(以秒为单位)为随机数生成器提供种子 - 这是通常完成的方式,但也有更安全的解决方案。

rand() % 12will give you a number between 0 and 11 (%is the modulus operator), so we add 1 here to get to your desired range of 1 to 12.

rand() % 12会给你一个 0 到 11 之间的数字(%是模运算符),所以我们在这里加 1 以获得你想要的 1 到 12 的范围。

In order to print 01 02 03 and so on instead of 1 2 3, you can format the output:

为了打印 01 02 03 等而不是 1 2 3,您可以格式化输出:

printf("Random number between 01 and 12: %02d", (rand() % 12) + 1);

回答by Roo

(rand() % 12 + 1).ToString("D2")

(rand() % 12 + 1).ToString("D2")