【问题标题】:How to get random numbers with the wrong generator如何使用错误的生成器获取随机数
【发布时间】:2011-10-08 05:04:16
【问题描述】:

问题:假设您有一个随机数生成器 randn(),它返回一个介于 0 和 n-1 之间的均匀分布的随机数。给定任意数 m,编写一个随机数生成器,返回一个介于 0 和 m-1 之间的均匀分布的随机数。

我的回答:

-(int)randm() {
    int k=1;
    while (k*n < m) {
        ++k;
    }
    int x = 0;
    for (int i=0; i<k; ++i) {
        x += randn();
    }
    if (x < m) {
        return x;
    } else {
        return randm();
    }
}

这是正确的吗?

【问题讨论】:

  • 你有没有关于nm的更多信息?
  • 部分问题是我需要对 n 和 m 做出什么假设才能完成这项工作,但我认为它适用于任何数字。
  • 你假设关于 n,m 的一些事情:1) 都是整数,2) 都是正数

标签: objective-c algorithm random


【解决方案1】:

你已经接近了,但你的答案的问题是有不止一种方法可以将一个数字写成其他两个数字的总和。

如果m&lt;n,那么这是可行的,因为数字0,1,...,m-1 出现的概率均相等,并且算法几乎肯定会终止。

这个答案通常不起作用,因为有不止一种方法可以将一个数字写为两个其他数字的总和。例如,只有一种方法可以得到0,但有很多方法可以得到m/2,所以概率不会相等。

示例n = 2m=3

0 = 0+0
1 = 1+0 or 0+1
2 = 1+1

所以你的方法的概率分布是

P(0)=1/4
P(1)=1/2
P(2)=1/4

这是不统一的。


要解决此问题,您可以使用唯一分解。在基数n 中写入m,跟踪所需的最大指数,例如e。然后,找到小于n^em 的最大倍数,称之为k。最后,用randn()生成e数字,以n为基数扩展某个数字x,如果是x &lt; k*m,则返回x,否则重试。

假设m &lt; n^2,那么

int randm() {

    // find largest power of n needed to write m in base n
    int e=0;
    while (m > n^e) {
        ++e;
    }

    // find largest multiple of m less than n^e
    int k=1;
    while (k*m < n^2) {
        ++k
    }
    --k; // we went one too far

    while (1) {
        // generate a random number in base n
        int x = 0;
        for (int i=0; i<e; ++i) {
            x = x*n + randn(); 
        }
        // if x isn't too large, return it x modulo m
        if (x < m*k) 
            return (x % m);
    }
}

【讨论】:

    【解决方案2】:

    这是不正确的。

    您正在添加统一的随机数,这不会产生统一的随机结果。假设 n=2 和 m = 3,那么 x 的可能值为 0+0、0+1、1+0、1+1。所以你得到 1 的可能性是得到 0 或 2 的两倍。

    您需要做的是以 n 为底写 m,然后生成随机数的以 n 为底的表示形式的“数字”。当你有完整的数字时,你必须检查它是否小于 m。如果是,那么你就完成了。如果不是,那么您需要重新开始。

    【讨论】:

      【解决方案3】:

      两个均匀随机数生成器的和不是均匀生成的。例如,两个骰子的和更可能是 7 而不是 12,因为要得到 12,你需要掷两个 6,而你可以得到 7 作为 1 + 6 或 6 + 1 或 2 + 5 或 5 + 2 或...

      假设 randn() 返回 0 和 n - 1 之间的整数,n * randn() + randn() 均匀分布在 0 和 n * n - 1 之间,因此可以增加它的范围。如果 randn() 返回一个介于 0 和 k * m + j - 1 之间的整数,则重复调用它直到得到一个数

      【讨论】:

        【解决方案4】:

        假设 n 和 m 都是正整数,那么标准的缩放算法不工作吗?

        return (int)((float)randn() * m / n);
        

        【讨论】:

        • 分布不均匀,除非 n 是 m 的精确倍数。如果 m > n,一些值将丢失。 (尝试 m=3,n=2:你只会得到 0 和 1,永远不会得到 2。)如果 m
        • 啊,好吧,有道理。没想到。谢谢。我将把我的答案留在这里而不是删除它,因为您的评论很好地解释了为什么它不起作用。
        猜你喜欢
        • 2011-05-05
        • 2016-08-15
        • 2019-06-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-01-02
        • 2015-03-14
        • 1970-01-01
        相关资源
        最近更新 更多