生成具有指定上限(0-n)的随机int,而不使用/或%

Generate random int with specified upper-bound (0 - n) without using / or %

本文关键字:int 随机 0-n      更新时间:2023-10-16

室友去面试,得到了这个:

规则:

允许使用rand((;

RAND_MAX=32767;

不使用除法或模;

TODO:编写一个函数,该函数接受一个int参数并返回int在0范围内-参数。

头疼,睡不着。感谢您的帮助。感谢

少数可能性:

  • 距离换位方法:int r = rand() * 0.00003051855095 * n;

  • "混洗排序"方法:int r; do { r = random(); } while (r >= n);

  • BSD方法:uint32_t r = arc4random_uniform(n);

等等。,等等。

在我的公共域randlib中,我使用没有浮点,没有除法,没有乘法,只有位掩码和拒绝采样,就像这样:

int ojr_rand(ojr_generator *g, int limit) {
    int v, m = limit - 1;
    m |= m >> 1;
    m |= m >> 2;
    m |= m >> 4;
    m |= m >> 8; // m is smallest ((power of 2) - 1) > limit
    do {
            v = m & NEXT16(g);  // 16-bit random number
    } while (v >= limit);
    return v;
}

在最坏的情况下(极限是二加一的幂(,这可以拒绝近50%的生成数字,但它仍然比大多数快速RNG的除法或浮动数学更快,在一般情况下它要快得多。此外,与浮点数学或mod不同,它是精确,这意味着如果你要求极限为3,你会得到完全相等概率的值0、1和2,而不仅仅是近似相等。

如果允许c++11,则提供了一个随机标头,使其变得微不足道:

#include <random>
#include <iostream>
int Roll(int Max)
{
    if(Max>32767)
        Max=32767;
    std::random_device generator;
    std::uniform_int_distribution<int> distribution(0,Max);
    return distribution(generator);   
}

int main()
{
    std::cout << Roll(10) << std::endl
              << Roll(10) << std::endl
              << Roll(999999) << std::endl;
}

更多详细信息,请访问:http://en.cppreference.com/w/cpp/numeric/random

这假设RAND_MAX是由您的问题提供的,而不是由C标准提供的。当然,您可以使用提供的常量,有关详细信息,请参阅:http://en.cppreference.com/w/cpp/numeric/random/RAND_MAX

do { r = random();} while (r >= max_rand);

起初,我认为乘以分数会奏效,但从数学的角度来看,这可能被认为是作弊。

int getRand(int max)
{
    int val = rand();
    while (val > max)
    {
        val -= max + 1;
    }
    return val;
}

通过计数值<=RAND_MAX % max比其他任何东西都多一次,但rand() % max有相同的问题,所以我认为这个错误是可以接受的(对于max<<MAX_RAND的值,这个错误是不重要的(。