为什么这个素数算法有效?

时间:2015-11-13 13:32:26

标签: c primes

#define _CRT_SECURE_NO_WARNINGS

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

int main() {
    int anz;
    scanf("%d", &anz);
    time_t start = time(0);
    int *primZ = malloc(anz * sizeof(int));
    primZ[0] = 2;
    int Num = 0;

    for (int i = 1, num = 3; i < anz; num += 2) {
        for (int j = 1; j < i; j++) {
            if (num % primZ[j] == 0) {
                num += 2;
                j = 0;
            }

            //this part
            if (primZ[j] > i / 2)
                break;
        }

        primZ[i] = num;
        i++;
        printf("%d ,",num);
    }

    time_t delta = time(0) - start;
    printf("%d", delta);
    getchar();
    getchar();
    return 0;
}

代码完美无缺,问题就是原因。部分if(primZ[j] > i/2)使程序快2到3倍。它实际上意味着if(primZ[j] > num/3)这是完全合理的,因为num只能是一个奇数。但它是找到的素数的数量。对我来说完全是无稽之谈。请解释一下。

3 个答案:

答案 0 :(得分:4)

通过检查素数是否可以被已找到的素数整除来检查素数是否是复合的。但是这样做你只需要检查并包括数字的平方根,因为任何大于除数字的数字都会留下比数字的平方根更小的数字。

例如33是复合的,但你只需检查最多5的数字即可实现,你不需要检查它是否可以被11整除,因为它留下3(33/11 = 3)我们已经检查过了

这意味着您可以通过

改进算法
    for (int j = 1; j < i; j++) {
        if( primZ[j]*primZ[j] > num )
             break;

        if (num % primZ[j] == 0) {
            num += 2;
            j = 0;
        }
    }

您可以通过与i/2的切割比较而得出的原因是由于素数的分布。素数计数函数大约为i = num/log(num),然后你得到i/2 > sqrt(num)

答案 1 :(得分:2)

原因是实际界限比$result = MyModel::search(...); $filteredResult = array_filter($result->toArray(), function ($el) { $availablePassengers = unserialize($el['passengers']); return count(array_intersect($availablePassengers, $this->passengers)); }); 严格得多 - 你可以使用:

num/3

的原因是如果一个素数高于if (primZ[j] > sqrt(num)) 的平方根除num,那么还必须有一个较低的素数(因为结果)这种划分必须低于平方根。

这意味着只要num高于i/2,代码就可以运行。会发生的是,低于数字的素数比更快比该数字的平方根增长,这意味着(完全意外地)sqrt(num)是一个安全的约束。

您可以查看i/2值的行为here - 他们称之为pi(x),素数小于x。

答案 2 :(得分:0)

这是有道理的,因为如果n有两个因子,其中一个肯定小于或等于n / 2,那么感觉程序在i中没有primZ的因子小于或等于等于i/2,这意味着当然没有i - 除了1的因素。

感知primZ按升序排序,j只会增加,当primeZ[j] > i/2表示iprimZ的因子不小于i / 2时。

P.S。开始搜索的要点在for语句num=3的第一部分中说明,而经常性语句num += 2确保您只测试奇数