为什么我的C代码仅每三个随机数生成一次?

时间:2019-03-26 22:06:23

标签: c random simulation

我正在尝试模拟蠕虫在由100,000台计算机组成的网络中的传播。模拟本身非常简单,除了出于某种原因,我只需要获得第三个随机数,就不需要任何帮助。

仅可对以1000为模的索引的计算机小于10,因此当感染1000台计算机时,应执行该程序。由于某种原因,我的程序只能得到329。当我降低目标数并检查数组的内容时,只有每三台计算机都被更改了,这是一个一致的模式。例如,在阵列的末尾,即使同时更改了(98002、98003等)之间的计算机,也仅更改了计算机98001、98004、98007、99002、99005、99008。该模式一直保持到数组的开头。当我尝试全部更改1000个时,程序进入无限循环并停留在329。

编辑:我刚刚发现,如果我将NETSIZE降低到10,000,而while循环中的目标降低到100,它不会跳过任何内容。这是否意味着问题与舍入错误有关?比我更了解C的人必须知道答案。

谢谢。

#include <stdio.h>
#include <stdlib.h>

#define NETSIZE 100000

double rand01();
void initNetwork();

unsigned char network[NETSIZE];
int scanrate = 3;
int infectedCount;
int scans;
int ind;
int time;



int main(void) {
    initNetwork();
    time = 0;
    infectedCount = 1;
    while (infectedCount < 1000) { //changing 1000 to 329 stops the infinite loop
        scans = infectedCount * scanrate;
        for (int j = 0; j < scans; j++) {
            ind = (int) (rand01() * NETSIZE);
            if (network[ind] == 0) {
                network[ind] = 1;
                infectedCount++;
            }
        }
        time++;
    }
    for (int k = 0; k < NETSIZE; k++) {
        if (network[k] == 1) printf("%d at %d\n", network[k], k);
    }
}
double rand01() {
    double temp;
    temp = (rand() + 0.1) / (RAND_MAX + 1.0);
    return temp;
}

void initNetwork() {
    for (int i = 0; i < NETSIZE; i++) {
        if (i % 1000 < 10) {
            network[i] = 0;
        } else  {
            network[i] = 2;
        }
    }
    network[1000] = 1;
}

在上面的代码中,我希望代码能够运行,直到1000个易受攻击的索引从0更改为1。

2 个答案:

答案 0 :(得分:3)

将评论转换为答案。

您的系统上的RAND_MAX是什么?如果它是15位或16位值,则转换为double时可能无法获得足够好的量化。如果它是31位或更大的数字,那么(可能)就不成问题了。您需要研究仅由rand01()函数使用不同种子生成的值,再乘以乘法并转换为整数-只需打印结果和sort -n | uniq -c即可查看结果的一致性。

  

在我的系统上,RAND_MAX只有32767。您认为这可能就是为什么我的结果可能不够细致的原因吗?现在您已经让我考虑了一下,将只有32,767个可能的值,而我的网络数组是100,000个可能的值。大约相当于我获得的1/3结果。

是的,我认为这很可能是问题所在。您想要100,000个不同的值,但是您的随机数生成器只能生成大约33,000个不同的值,这非常接近您的1:3指标。这也立即说明了当您将乘数从100,000减少到10,000时为什么会得到良好结果的原因。

您可以尝试:

double rand01(void)
{
    assert(RAND_MAX == 32767);
    return ((rand() << 15) + rand()) / ((RAND_MAX + 1.0) * (RAND_MAX + 1.0));
}

或者您可以使用其他随机数生成器-例如,POSIX定义了drand48()函数家族和 random(),并在需要时提供相应的种子设置功能。<​​/ p>

答案 1 :(得分:0)

是的,我遇到的问题是系统上的RAND_MAX值仅为32767,我正试图将其有效地散布到100,000个值中,从而导致仅出现三分之一的数字。

在我的辩护中,建议rand01()函数的人拥有计算机科学博士学位,但我认为他在我们学校的主计算机上运行了此代码,该代码可能具有更大的RAND_MAX值。

@JonathanLeffler值得赞扬的是该解决方案。