【问题标题】:Find a random number generator using a given random number generating function使用给定的随机数生成函数查找随机数生成器
【发布时间】:2013-06-19 11:45:12
【问题描述】:

这是一道面试题:

给定一个在 [1,5] 范围内生成随机数的函数,我们需要使用该函数在 [1,9] 范围内生成一个随机数。 我想了很多,但无法写出满足随机性的方程。 请大家回答。这可能对未来的一些采访有帮助。

【问题讨论】:

  • 你也想要均匀的概率分布吗?
  • 我猜这就是随机性的意思。
  • 考虑到问题的提出方式,我相当确定它必须产生均匀分布。否则问这个问题是没有意义的。
  • 生成的函数是生成整数还是实数?
  • 您可以使用不具有均匀概率分布的随机数生成器。一个简单的例子是掷两个六面骰子。这当然是随机的,但你掷出 12 的可能性比掷出 7 的可能性要小得多。

标签: algorithm random number-theory


【解决方案1】:

改编自“Expand a random range from 1–5 to 1–7

它假设 rand5() 是一个函数,它返回一个统计随机整数,范围在 1 到 5 之间。

int rand9()
{
    int vals[5][5] = {
        { 1, 2, 3, 4, 5 },
        { 6, 7, 8, 9, 1 },
        { 2, 3, 4, 5, 6 },
        { 7, 8, 9, 0, 0 },
        { 0, 0, 0, 0, 0 }
    };

    int result = 0;
    while (result == 0)
    {
        int i = rand5();
        int j = rand5();
        result= vals[i-1][j-1];
    }
    return result;
}

它是如何工作的?可以这样想:想象在纸上打印出这个二维阵列,将其钉在飞镖板上,然后随机向其投掷飞镖。如果您达到一个非零值,它是一个介于 1 和 9 之间的统计随机值,因为有相同数量的非零值可供选择。如果您击中零,请继续投掷飞镖,直到击中非零为止。这就是这段代码的作用:i 和 j 索引随机选择飞镖板上的一个位置,如果我们没有得到好的结果,我们就会继续投掷飞镖。

这可以在最坏的情况下永远运行,但从统计上来说,最坏的情况永远不会发生。 :)

【讨论】:

  • 只是好奇,如果我们有一个在 [1,5] 范围内生成随机数的函数,是否意味着我们只能创建另一个在 [1,25] 范围内生成随机数的函数最多? [1,26] 怎么样,有可能吗?
【解决方案2】:
int rand9()
{
    int t1,t2,res = 10;
    do {
        t1 = rand5();
        do {
            t2 = rand5();
        }while(t2==5);
        res = t1 + 5* (t2%2);
    }while(res==10);
    return res;
}

现在 1 到 9 的概率是 1/9。

解释一下:

t1 有 1/5 的概率是 1 到 5。

t2,too.but 当 t2==5,discarded.so t2 有 1/4 的概率是 1 到 4。也就是说,1/2 的概率是奇数或偶数,这使得 t2% 2 有 1/2 的概率是 0 到 1。

因此,t1 + 5*(t2%2) 有 5/10 为 1 到 5 的概率,5/10 为 6 到 10 的概率。 但是10又被丢弃了,所以剩下9个数字的概率是1/9。

【讨论】:

  • 这也不是随机的,数字 2 和 4 出现的次数是其余数字的两倍,而 9 则根本没有。
  • 我已将 res = t1*(1+ t2%2) 更改为 res = t1+ 5* t2%2,现在可以使用了。
  • 不,它没有。现在的代码产生从 1 到 6(而不是 7-9)的数字,并且 2-5 的出现频率是 1 和 6 的两倍。我有一个 LINQPad 程序在这里你可以尝试向你展示:@987654322 @
  • @LasseV.Karlsen 你是对的,我发现我在 t2%2 之外遗漏了括号,这不是我最初的想法。当我将它们加起来并使用(1+rand()%5) 作为 rand5(),它工作正常。我修复了我的代码并添加了一些解释。
【解决方案3】:

您需要使用rejection sampling。也就是说,拒绝不符合您的目标分布的结果。在您的情况下,您可以使用对 rand15 函数的两次连续调用的低三位(必要时为 - 1),将它们连接起来并拒绝那些超出目标区间的结果,然后重试,直到找到里面的数字。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-09-18
    • 1970-01-01
    • 2015-03-14
    • 2023-01-03
    • 1970-01-01
    • 1970-01-01
    • 2018-04-03
    • 1970-01-01
    相关资源
    最近更新 更多