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

时间:2013-05-28 20:31:56

标签: c++ algorithm random bit-manipulation

室友接受了采访并得到了这个:

规则:

允许使用rand();

RAND_MAX = 32 767;

不使用除法或模数;

TODO: 编写一个带有一个int参数并返回的函数 int在范围0 - 参数。

头疼,无法入睡。任何帮助赞赏。 感谢

5 个答案:

答案 0 :(得分:4)

几种可能性:

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

  • “随机排序”方法:int r; do { r = random(); } while (r >= n);

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

等等,等等。

答案 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

答案 2 :(得分:2)

在我的公共领域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;
}

在最坏的情况下(限制是2加1的功率),这可以拒绝接近50%的生成数字,但它仍然比使用最快RNG的除法或浮动数学快,并且在一般情况下它很多快点。此外,与浮点数学或模拟不同,它是精确,这意味着如果要求限制为3,则获得的值为0,1和2的概率几乎相等,而不仅仅是大致相等。

答案 3 :(得分:1)

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

起初我认为乘以一个分数会起作用,但从数学的角度来看,这可能被视为作弊。

答案 4 :(得分:-1)

int getRand(int max)
{
    int val = rand();

    while (val > max)
    {
        val -= max + 1;
    }

    return val;
}

这显然会稍微偏离计数值RAND_MAX % max一次,但rand() % max具有相同的问题,所以我认为这个错误是可以接受的({{1} }}&lt;&lt; max错误是无关紧要的。)