给定一个函数,它产生的是1到5之间的随机整数,写一个函数,它产生的是1到7之间的随机整数。


当前回答

这里似乎没有提到的另一个答案:

int rand7() {
  int r = 7 / 2;
  for (int i = 0; i < 28; i++)
    r = ((rand5() - 1) * 7 + r) / 5;
  return r + 1;
}

在每次迭代中,r是一个0到6之间的随机值。它被追加(以7为基数)到一个0到4(包括4)之间的随机值,结果除以5,得到一个0到6(包括6)范围内的新随机值。R开始时有很大的偏差(R = 3是非常有偏差的!),但每次迭代都将偏差除以5。

这种方法不是完全均匀的;然而,偏差是微乎其微的。数量级为1/(2**64)这种方法的重要之处在于它具有恒定的执行时间(假设rand5()也具有恒定的执行时间)。理论上不需要担心一个不走运的调用可能永远迭代地选择坏值。


此外,还有一个讽刺的回答(有意无意,它已经被覆盖了):

1-5已经在1-7的范围内,因此下面是一个有效的实现:

int rand7() {
  return rand5();
}

问题没有要求均匀分布。

其他回答

下面是一个利用c++ 11特性的答案

#include <functional>
#include <iostream>
#include <ostream>
#include <random>

int main()
{
    std::random_device rd;
    unsigned long seed = rd();
    std::cout << "seed = " << seed << std::endl;

    std::mt19937 engine(seed);

    std::uniform_int_distribution<> dist(1, 5);
    auto rand5 = std::bind(dist, engine);

    const int n = 20;
    for (int i = 0; i != n; ++i)
    {
        std::cout << rand5() << " ";
    }
    std::cout << std::endl;

    // Use a lambda expression to define rand7
    auto rand7 = [&rand5]()->int
    {
        for (int result = 0; ; result = 0)
        {
            // Take advantage of the fact that
            // 5**6 = 15625 = 15624 + 1 = 7 * (2232) + 1.
            // So we only have to discard one out of every 15625 numbers generated.

            // Generate a 6-digit number in base 5
            for (int i = 0; i != 6; ++i)
            {
                result = 5 * result + (rand5() - 1);
            }

            // result is in the range [0, 15625)
            if (result == 15625 - 1)
            {
                // Discard this number
                continue;
            }

            // We now know that result is in the range [0, 15624), a range that can
            // be divided evenly into 7 buckets guaranteeing uniformity
            result /= 2232;
            return 1 + result;
        }
    };

    for (int i = 0; i != n; ++i)
    {
        std::cout << rand7() << " ";
    }
    std::cout << std::endl;

    return 0;
}

这个解决方案不浪费任何熵,并给出了范围内第一个可用的真正随机数。随着每一次迭代,得不到答案的概率可证明地降低了。在N次迭代中得到答案的概率是0到max (5^N)之间的随机数小于该范围内7的最大倍数(max-max%7)的概率。必须迭代至少两次。但这对所有解都是成立的。

int random7() {
  range = 1;
  remainder = 0;

  while (1) {
    remainder = remainder * 5 + random5() - 1;
    range = range * 5;

    limit = range - (range % 7);
    if (remainder < limit) return (remainder % 7) + 1;

    remainder = remainder % 7;
    range = range % 7;
  }
}

数值上等价于:

r5=5;
num=random5()-1;
while (1) {
   num=num*5+random5()-1;
   r5=r5*5;
   r7=r5-r5%7;
   if (num<r7) return num%7+1;
}

第一个代码以模形式计算。第二个代码只是简单的数学。或者我在某个地方犯了错误。: -)

这是我想到的答案,但这些复杂的答案让我认为这是完全错误的/:))

import random

def rand5():
    return float(random.randint(0,5))

def rand7():
    random_val = rand5()
    return float(random.randint((random_val-random_val),7))

print rand7()

我首先想到的是这个。但我不知道它是否均匀分布。 在python中实现

进口随机 def rand5 (): 返回random.randint(1、5) def rand7 (): 返回((rand5() -1) * rand5()) %7)+1

以下是我的发现:

Random5产生1~5的范围,随机分布 如果我们运行3次并将它们加在一起,我们将得到3~15个随机分布的范围 在3~15范围内执行算术 (3~15) - 1 = (2~14) (2~14)/2 = (1~7)

然后我们得到1~7的范围,这是我们正在寻找的Random7。