【问题标题】:Testing C Random Number Generator测试 C 随机数生成器
【发布时间】:2015-09-15 18:12:54
【问题描述】:

我正在做一个项目,但我不知道如何完成特定部分。

作业是“编写一个程序来确定C随机数生成器是否真的生成均匀随机数。你将通过创建一个包含20个整数的数组然后生成200,000个0到19(含)之间的随机数来做到这一点. 对于生成的每个随机数 n,将数组的第 n 个元素加 1。如果 C 随机数生成器是统一的,那么数组中的每个元素最终应该具有大致相同的值。 要确定是否是这种情况,您需要打印数组。您还需要打印出数组的最小值和最大值,以及平均值和标准差。”

但是,对于生成的每个随机数 n,我需要帮助,将数组的第 n 个元素增加 1。我不太确定要问什么或如何去做吧。我不是要求代码来完成它,而是我应该使用什么来完成它。

我对 C 还很陌生,所以如果这是一个明显的答案,请提前道歉。

【问题讨论】:

  • 这看起来像家庭作业 - 你到目前为止写了什么代码。
  • 这是一件非常微不足道的事情。如果不给出答案,我什至不知道如何解释。
  • 假设您有一个由 20 个“桶”组成的数组,因此对于您生成的每个随机数,您检查它落在哪个桶中并增加每个桶的计数器;最后,您检查每个桶的计数,如果它们都(或多或少)相同的计数,那么您的随机数将统一生成。
  • 定义更多或更少。

标签: c arrays random numbers


【解决方案1】:

这个数组可能被描述性地命名为count[20],在你开始之前每个元素都初始化为0。所以问题描述中提到的增量只是将该随机数的计数加 1。例如,如果生成 17,则每次发生时都会增加 count[17]。完成后,count[17] 会告诉您 17 从该生成器中产生了多少次。

【讨论】:

    【解决方案2】:

    伪代码:

    int bucket[20] = {0, };            // all values start at 0
    for (int i = 0; i < 200000; ++i) { // you need 200000 random values
        int j = random(0, 20);         // produce a number between 0 and 19
        bucket[j] = bucket[j] + 1;     // increment the appropriate counter
    }
    

    【讨论】:

    • 为什么投反对票——我的伪代码是否错过了问题的目的?
    • 也许是 OP 的“我不是要求代码来做”?
    【解决方案3】:

    这可能会让你开始:

    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    
    #define SIZE 20
    #define TRIALS 200000
    
    int
    main (int argc, char* argv[])
    {
        srand(time(NULL));
        int counter[SIZE] = {0};
        for (int trial = 0; trial < TRIALS; trial++) {
            counter[rand() % SIZE]++;
        }
        for (int idx = 0; idx < SIZE; idx++) {
            fprintf(stdout, "%02d %d\n", idx, counter[idx]);
        }
        return EXIT_SUCCESS;
    }
    

    rand() 函数生成一个介于 0 和 RAND_MAX 之间的数字,保证至少为 32767。当您对该值执行 modulus operation 时,模数小于 RAND_MAX,您会得到一个介于 0 和模数之间的数字。

    所以代码rand() % SIZE 会生成一个介于 0 和 19 之间的随机值,包括 0 和 19。您可以将此值用作数组counter 的索引。

    这应该足以让您计算出最小值、最大值。以及其余的统计计算。

    提示:20 不是 RAND_MAX + 1 的倍数,所以这应该告诉你模运算是否可以均匀地——均匀地——甚至在你做这个练习之前。

    【讨论】:

    • 你认为如果人们做作业,发帖者会学到什么吗?
    • 不确定,但是网络上的代码 sn-ps 太多了,这个家庭作业可能已经回答了很多次了。主要是想解释一下rand()是如何工作的,为什么模运算可以和rand()一起使用来解决编码部分的问题,并建议原始问题(“RNG是否在给定的界限?”)可以根据提供的参数在不进行任何随机抽样的情况下回答。
    • 模偏差是 rand() 使用的种子循环的组合,通常为 2^32,模 (RAND_MAX+1),在本例中为模 20。由于 2^ 32 通常是 RAND_MAX+1 的倍数,没有问题,但模 20 会产生偏差。还有一个偏差,因为在 rand() 循环的 4,294,967,296 个数字中只有 200,000 个被使用。
    • 是的,没错。另一种更简单的思考方式是,如果你掷一个四面骰子来获得随机数,然后对出现的任何数字应用mod 3。换句话说,{1, 2, 3, 4} 的可能性被映射到{1, 2, 3, 1}。 1 出现的可能性是 2 和 3 的两倍,因为 3 不能平均划分 4。同样,20 不会均匀地划分RAND_MAX + 1,因此某些数字将被过度表示(平均而言),并且随机数分配给箱 1 到 20(或 0 到 19,具体取决于关于你如何计算)。
    • 如果所有 2^32 == 4,294,967,296 个数字都以 20 为模,那么对应于 4,294,967,297 到 4,294,967,300 以 20 为模的 4 个“缺失”数字将导致微小的偏差。每个余数 0 到 15 将出现 214,748,365 次,每个余数 16 到 19 将出现 214,748,364 次。在 RAND_MAX+1 == 2^15 = 32768 的情况下,对于所有 2^32 = = 4,294,967,296 个数字,0 到 7 会出现 214,827,008 次,8 到 19 会出现 214,695,936 次。
    猜你喜欢
    • 1970-01-01
    • 2011-01-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多