【发布时间】:2019-08-17 09:51:05
【问题描述】:
我正在尝试模拟蠕虫在由 100,000 台计算机组成的网络中的传播。模拟本身非常简单,我不需要任何帮助,除了出于某种原因,我只得到每三个随机数。
只有索引模1000小于10的计算机才会被感染,所以当1000台计算机被感染时,程序应该被执行。由于某种原因,我的程序只得到 329。当我降低目标编号并检查数组的内容时,只有每三台计算机发生了变化,这是一个一致的模式。例如,在阵列的末尾,只有计算机 98001、98004、98007、99002、99005、99008 被更改,即使中间的计算机(98002、98003 等)也应该更改。该模式一直保持到数组的开头。当我尝试更改所有 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。
【问题讨论】:
-
请说明您对
temp = (rand() + 0.1) / (RAND_MAX + 1.0);这一行的意图和理解。尤其要详细说明可能结果的范围。另请解释为什么您创建一个双随机数,然后将其用作 int。 -
测试
ind是否在if (network[ind] == 0) {之前的范围内 -
您系统上的
RAND_MAX是什么?如果它是 15 位或 16 位值,则在转换为double时可能没有得到足够好的量化。如果它是 31 位或更大的数字,那(可能)不会是问题。您需要研究仅由具有不同种子的rand01()函数生成的值,加上乘法并转换为整数 - 只需打印结果和sort -n | uniq -c即可查看结果的一致性。 (100,000 / 30,000 大约是 3 倍)。 -
@JonathanLeffler 在我的系统上,RAND_MAX 只有 32767。你认为这可能是我的结果不够精细的原因吗?既然您已经让我考虑过了,那么可能只有 32,767 个可能的值,而我的网络数组是 100,000 个可能的值。这大约相当于我得到的 1/3 结果。
-
是的,我认为这很可能是问题所在。您想要 100,000 个不同的值,但您的随机数生成器只能生成大约 33,000 个不同的值,这非常接近您的 1:3 指标。你可以试试
((rand() << 15) + rand()) / ((RAND_MAX + 1.0) * (RAND_MAX + 1.0))。
标签: c random simulation