C++ 如何从rand()缩小数字?

C++ 如何从rand()缩小数字?,c++,random,generator,mersenne-twister,C++,Random,Generator,Mersenne Twister,以下代码每秒输出一个随机数: int main () { srand(time(NULL)); // Seeds number generator with execution time. while (true) { int rawRand = rand(); std::cout << rawRand << std::endl; sleep(1); } } int main() {

以下代码每秒输出一个随机数:

int main ()
{
    srand(time(NULL)); // Seeds number generator with execution time.

    while (true)
    {
        int rawRand = rand();

        std::cout << rawRand << std::endl;

        sleep(1);
    }
}
int main()
{
srand(time(NULL));//种子数生成器,带执行时间。
while(true)
{
int rawRand=rand();

std::cout参见
man 3 rand
——您需要通过除以
rand_MAX
进行缩放以获得范围[0,1],然后您可以乘以100作为目标范围。

rawRand%101将给出[0-100],包括在内。

请参阅(有关更多详细信息):

其他人也指出,这不会给您提供尽可能好的随机数分布。如果这类事情在您的代码中很重要,您必须执行以下操作:

int rawRand = (rand() * 1.0 / RAND_MAX) * 100;

编辑

三年过去了,我正在进行编辑。正如其他人所提到的,
rand()
有很多问题。显然,在有更好的替代方案的情况下,我不能推荐使用它。您可以在这里阅读所有详细信息和建议:

你可以做

cout << rawRand % 100 << endl; // Outputs between 0 and 99

cout << rawRand % 101 << endl; // outputs between 0 and 100

对于从最小值到最大值(包括最大值)的范围,请使用:
int result=rand()%(max-min+1)+min;

到目前为止发布的所有示例实际上都给出了分布不均的结果。请经常执行代码并创建一个统计数据,以查看值是如何扭曲的

在任何范围[0,N]内生成真实均匀随机数分布的更好方法如下(假设
rand
实际上遵循均匀分布,这一点并不明显):

当然,这种方法很慢,但它确实产生了一个良好的分布。一种稍微聪明一点的方法是找到小于
RAND_MAX
的N的最大倍数,并将其用作上限。然后,可以安全地获取
结果%(N+1)


有关“朴素模量法”为何不好以及上述方法为何更好的解释,请参见Julienne关于“您希望答案的长度”的优秀文章

最简单的方法是使用除以101的余数进行转换:

int value = rawRand % 101;
半纯粹主义者会使用双重标准重新调整比例:

double dbl = 100 * ((double)rawRand / RAND_MAX);
int ivalue = (int)(dbl + 0.5);   // round up for above 0.5
一个纯粹主义者会说兰德不会产生随机数


请注意,随机数的质量是通过取一个数字序列,然后计算该序列源为随机数的数学概率来衡量的。如果你追求随机性,使用余数进行简单的黑客攻击是一个非常糟糕的选择。

一些人发布了以下代码作为示例:

int rawRand = (rand() / RAND_MAX) * 100;

这是一个无效的解决问题的方法,因为RAND()和RANDMAX都是整数。在C++中,这会导致积分除法,它将截断结果小数点。作为RANDMAX>>RAND(),该运算的结果是1或0,这意味着RaWand可以仅为0或100。

int rawRand = (rand() / static_cast<double>(RAND_MAX)) * 100;
int rawRand=(rand()/static_cast(rand_MAX))*100;

由于操作数是双的,使用浮点除法,它将返回0到1之间的正确值。

< P>如果你使用C++,并且关注好的分布,你可以使用Tr1 C++ 11代码> <代码>
#包括
std::随机测试设备;
std::mt19937 rgen(rseed());//mersenne_捻线机
标准::统一国际分布idist(0100);/[0100]

std::cout int GetRandom(){return 59;/*一个完全随机选取的数字*/}我看到的是一个xkcd引用吗?:Pnaah,看到的地方太多了,无法说出确切的来源,为了避免自己写它。睡眠时间以毫秒表示,请使用sleep(1000)睡眠一秒钟。@Nikola不在我使用的实现中,它不是。多么奇怪。From“注意,尽管这个模运算在跨度中不会生成真正均匀分布的随机数(因为在大多数情况下,较低的数字更可能),但它通常是短跨度的一个很好的近似值。”有趣。这个方法比模方法有什么优势吗?好吧,这取决于垃圾
rand()的程度
首先是。虽然它通常都是垃圾。不。不均匀性只是传播的方式不同。但是你仍然比其他人更经常地得到一些数字。+1我有点惊讶,这是唯一建议按
RAND_MAX
而不是
%
模数除法的答案。@Joey:重点是它避免了最令人发指的情况在实践中看到的不良行为。例如,LCG,其中最低有效位在连续样本上交替出现。因此,如果你使用偶数取模,你的值将具有相同的属性。如果你进行缩放,它们至少会闪避该子弹。
rand()
是允许它是一个残暴的PRNG。如果需要好的随机数,任何使用它的方法都是可疑的,但有些方法甚至比其他方法更可疑。请不要在实践中使用这种方法——它是不好的。请注意,从中会得到一个稍微不均匀的分布。这样,数字越少,出现的频率就越高。这是解决问题的好方法要了解这一点,请查看
java.util.Random#nextInt(int)
。正如我之前所说,使用模方法并不是完全随机的。100个数字,uint有648个0-100的完整范围,一个0-87的范围。因此,0-87的数字比88-100的数字出现的几率稍高。对于需要随机数的人,他们不会使用rand来生成它们。在由模数和重缩放范围调整引入的值只有在一开始有随机分布时才有意义。-1.仍然会得到非均匀分布。
rand()
具有rand_MAX+1值;除非它是101的倍数(可能不是)事实上,一个PRNG产生均匀分布的数字应该是你可以假设的。稍微聪明一点的w
double dbl = 100 * ((double)rawRand / RAND_MAX);
int ivalue = (int)(dbl + 0.5);   // round up for above 0.5
int rawRand = (rand() / RAND_MAX) * 100;
int rawRand = (rand() / static_cast<double>(RAND_MAX)) * 100;
#include <random>

std::random_device rseed;
std::mt19937 rgen(rseed()); // mersenne_twister
std::uniform_int_distribution<int> idist(0,100); // [0,100]

std::cout << idist(rgen) << std::endl;