为什么从 int i = 6 开始的 for 循环比 int i = 0 花费的时间更长?

Why does a for loop that start int i = 6 takes longer than int i = 0?

我已经用 C 编写了埃拉托色尼筛法,但是当我从 int i = 6 开始时,我的 for 循环需要更长的时间。

int *tmp = NULL;

tmp = malloc(sizeof(int) * 1000000);

tmp[0] = 2;
tmp[1] = 3;
tmp[2] = 5;

int prim_ = 3;
bool hasdiv = false;

clock_t t;
t = clock();
for(int i = 6; i < 1000000; i++) {
    for (int j = 0; j < prim_; j++){
        if (i % tmp[j] == 0) {
            hasdiv = true;
            break;
        }
    }
    if (!hasdiv) {
        prim_++;
        tmp[prim_] = i;
    }
    hasdiv = false;
}
t = clock() - t;
double tim = ((double)t) / CLOCKS_PER_SEC;

printf("%f",tim);

for(int i = 6; i < 1000000; i++) {

需要 8.4 秒

for(int i = 0; i < 1000000; i++) {

需要 0.009 秒。行为从何而来?

我使用 VS 19 社区和 MSVC 14.24.28314。

首先,请注意您的代码有一个错误,即 tmp[3] 永远不会被初始化:您从 3 开始 prim_ 并在分配给 tmp[prim_] 之前递增它.因此,每次 j==3 循环时,您都会读取未初始化的内存,并且您的代码具有未定义的行为。您可能想要交换 prim_++; tmp[prim_]=i; 行,或者只是写 tmp[prim_++]=i;.

解决这个问题后,想想当你使用 i==1 进行循环时会发生什么。 1 不能被任何大于 1 的整数整除,因此您的代码将断定它是质数,并将设置 tmp[3]=1。由于每个数字都可以被 1 整除,因此在外循环的每次后续迭代中,您将在 j==3 时立即跳出内循环。这显然比 j 必须一直上升到 prim_ 要快得多。它还将使您的程序变得毫无价值,因为它将决定没有超过 5 的素数。

大多数处理素数的逻辑都需要数字 1 的特例,这也不例外。对于您的程序来说,以小于 2 的 i 值开始确实没有任何意义。