C语言重来53:数组的例子:素数

文章探讨了不同方法来判断一个数是否为素数,从基础的逐个测试除法到优化后的排除偶数和利用已知素数表。通过改进循环条件和减少测试次数,提高了算法效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

首先祝大家新年快乐。

在之前的求素数的时候,我们并没有使用数组。

但是这个程序过于臃肿了,我们这个判断的方法是从2到x-1挨个测试是否可以整除,但是当n很大的时候,就会循环很多遍,这样的话这个程序的效率也会很低。

int isPrime(int x)
{
    int ret = 1;
    int i;
    if (x == 1)
        ret = 0;
    for(i = 2; i < x; i++)
    {
        if (x%i == 0)
        {
            ret = 0;
            break;
        }
    }
    return ret;
}

还有一种方法就是在循环前先把所有的偶数排除,注意重点是判断是否为2,然后再从3开始把后面的所有奇数挨个循环一遍,这种方法会好一点,可能会循环(n-3)/2+1遍,当n很大的时候就是n/2遍。

int isPrime(int x)
{
    int ret = 1;
    int i;
    if (x == 1||(x%2==0&&x!=2))
        ret = 0;
    for(i = 3;i < x; i+=2)
    {
        if (x%i == 0)
        {
            ret = 0;
            break;
        }
    }
    return ret;
}

还有一种方法就是循环的时候不用走到x-1,而是走到x-1的开根就可以了。

具体的原理就是把x硬拆成两个数字的乘积,然后判断带根号的这一部分能不能被小于它的数字整除。

同时需要注意的是如果要使用sqrt的话,那么在函数的前头是要标记一个函数的名称的:

include<math.h>

int isPrime(int x)
{
    int ret = 1;
    int i;
    if (x == 1 || (x % 2 == 0 && x != 2))
        ret = 0;
    for (i = 3; i < sqrt(x); i += 2)//注意到这里的时候是要在前面加上#include<math.h>
    {
        if (x % i == 0)
        {
            ret = 0;
            break;
        }
    }
    return ret;
}

还有一种更好的方法就是,不拿更小的数来判断是否能够整除,而是使用更小的素数来进行整除。

但是这个方法有一个要求是我们需要一个已经存在的素数的表格,来进行原数对小的素数的是否整除的判断。

然后我们的目的就是写出一个有关于素数的函数。

具体的解释以及程序会在注释中写出:

//这个程序是用来输出所有的小于输入的数的素数。
#include<stdio.h>
//这个自定义函数是用来判断当前的这个数是不是素数。
int isPrime(int x, int knowPrimes[], int number0fKnownPrimes)
{
    int ret = 1;
    int i;
    for (i = 0; i < number0fKnownPrimes; i++)
    {
        if (x % knowPrimes[i] == 0)
        {
            ret = 0;
            break;
        }
    }
    return ret;
}
int main()
{
    const int number = 10;//算出前number个素数。
    int prime[number] = { 2 };//初始第一个数字是2,后面的数字刚开始自动化为0,在后面的计算中来进行输出。
    int count = 1;//count的数组的第一个数字已经有值了,所以初始量为1,
    int i = 3;
    //为了对应后面的每一个prime里面的变量的输出,所以在这里定义一个表头。
    {
        int i;
        printf("\t\t");//这个制表符根据程序实际的空格来进行判断,不同的编译器有不同的空格方法。
        for (i = 0; i < number; i++)
        {
            printf("%d\t", i);
        }
        printf("\n");    
    }
    while (count < number)
    {
        if (isPrime(i, prime, count))
        {
            //由于前面已经赋值了数组第一个,所以这边从count=1开始。
            prime[count++] = i;//如果判断结果是素数的话,就挨个放入这个数组。
            //注意这里是先对prime[count]赋值,然后再让count+1.这就是前面所说的副作用。
        }
        {//这个大括号里面的都是调试语句。
            //输出的i是第几个测试的数字,count是计数有几个素数。
            printf("i=%d\tcnt=%d\t", i, count);//在定义自己的i的时候,可以把外面的i输出。
            int i;//定义一个属于调试语句的变量,里面定义的i和外面的i并不冲突。
            for(i=0;i<number;i++)//遍历prime数组并且把数组中的每一个数都输出。
            {
                printf("%d\t", prime[i]);
            }
            printf("\n");
        }
        i++;//测试完上一个数,开始测试下一个数。
    }
    for (i = 0; i < number; i++)
    {
        printf("%d", prime[i]);
        if ((i + 1) % 5)
            printf("\t");
        else
            printf("\n");
    }
    return 0;
}

还是可以看出,这样的方法还是有一点麻烦的,我们可以换一种方法,就是输出一个表,把里面不是素数的标记,最后输出的就是素数。

具体分为一下几步:

  1. 令x为2,

  1. 将2x,3x,4x,直至ax<n的数标记为非素数,

  1. 令x 为下一个没有标记为非素数的数,重复2;直到所有的数都已经尝试完毕。

来写一个伪代码来看一下程序的具体的过程:

1.开辟prim[n],初始化其所有元素为1,prime[x]为1表示x为素数。
初始化所有数字为1,就是最后的判断,如果数组中的这个元素是1的话,那么它就是素数。
2.令x=2。
3.如果x是素数,则对于(i=2;x*i<n;i++)令prime[i*x]=0。
4.令x++,如果x<n,重复3,否则结束。
#include<stdio.h>
int main()
{
    const int maxNumber = 25;//求多少以内的素数。
    int isPrime[maxNumber];
    int i;
    int x;
    for (i = 0; i < maxNumber; i++)
    {
        isPrime[i] = 1;
    }
    for (x = 2; x < maxNumber; x++)
    {
        if (isPrime[x])
        {
            for (i = 2; i * x < maxNumber; i++)
            {
                isPrime[i * x] = 0;
            }
        }
    }
    for (i = 2; i < maxNumber; i++)
    {
        if (isPrime[i])
        {
            printf("%d\t", i);
        }
    }
    printf("\n");
    return 0;
}

最后的输出素数表的程序就是这样的。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值