c语言一到十的素数除法,c语言:实现对于给定的正整数N,依次打印出小于等于N的所有素数。两种方法及其优化...

请编写一个程序,实现对于给定的正整数N,依次打印出小于等于N的所有素数。

方法一:试除法

由素数的定义得到如下程序:

#include

int print_prime(int num)//prime表示素数

{

int i = 0;

for (i = 2; i <= num; i++)

{

int j = 0;

for (j = 2; j < i; j++)

{

if (i%j == 0)

{

break;

}

}

if (i==j)

{

printf("%d\t",i);

}

}

}

int main()

{

int num;

printf("请输入一个正整数:");

scanf("%d", &num);

if (num > 1)

{

printf("打印出所有的素数:");

print_prime(num);

}

else

{

printf("不存在小于等于%d的素数", num);

}

printf("\n");

return 0;

}

上面的代码中,在判断素数时一直从2试除到n-1。这里从n/2之后的数到n-1的试除显然是多余的,比如正整数7不能被2整除,必然不能被4,6整除。

优化1:

试除的范围优化到[2,n/2],则工作量减少一半,代码如下:

int print_prime(int num)//prime表示素数

{

int i = 0;

for (i = 2; i <= num; i++)

{

int j = 0;

for (j = 2; j <= i/2; j++)//修改部分

{

if (i%j == 0)

{

break;

}

}

if (j == (i/2+1))//修改部分

{

printf("%d\t", i);

}

}

}

既然能将试除范围优化到[2,n/2],那么这个范围是不是还能继续优化呢?答案是肯定的,在[2,n/2]这个范围里(√n,n/2]的试除也是多余的。因为因数是成对出现的,如16可分解为:1和16 、2和8、4和4、8和2、16和1。这些因数里必然有一个小于等于4。故只需试除小于等于√n的数就可以了。

优化2:

试除范围优化为[2,√n],代码如下:

#include

#include//修改部分

int print_prime(int num)//prime表示素数

{

int i = 0;

for (i = 2; i <= num; i++)

{

int j = 0;

for (j = 2; j <=sqrt(i); j++)//修改部分

{

if (i%j == 0)

{

break;

}

}

if (j > sqrt(i))//修改部分

{

printf("%d\t", i);

}

}

}

上面所有的代码在找素数的时候是从2到n,在这个范围内除了2之外的偶数都不是素数,所以可以跳过这些偶数。

还有试除范围内除了2之外的偶数也是没有必要的,因为如果不能被2整除,必然不能被大于2的偶数整除。

优化3:

寻找素数时和试除范围内跳过除2之外的偶数。代码如下:

int print_prime(int num)//prime表示素数

{

int i = 0;

printf("%d\t", 2);//修改部分

for (i = 3; i <= num; i+=2)//修改部分

{

int j = 2;

for (j = 3; j <= sqrt(i); j+=2)//修改部分

{

if (i%j == 0)

{

break;

}

}

if (j > sqrt(i))

{

printf("%d\t", i);

}

}

}

在上面的代码中,试除范围内的一些数也是不必要的。比如判断101是否为素数时,要分别试除小于10的2和所有奇数,即2、3、5、7、9,其中对9的试除是不必要的。即对所有的非素数的试除是不必要的,因为非素数必然可分解为比它小的素数的乘积,既然它的质因数不能整除某个数,这个数必然也不能。故试除的范围可缩小到小于等于√n的所有素数。

优化4:

只试小于√n的素数,那么问题来了,要试除这些素数时必然要将前面求出的素数保存起来,开辟多大一块空间合适呢?因为n的大小未知,所以无法确定开辟多少空间。这里暂时没有完全解决的办法,我的做法是先开辟大小为1000的空间,需要时再修改。

#include

#include

#define MAX 1000  //定义数组的大小

int print_prime(int num)//prime表示素数

{

int arr[MAX] = { 0 };

int i = 0,j=1;

printf("%d\t", 2);

arr[0] = 2;

for (i = 3; i <= num; i += 2)

{

int k = 0;

while (arr[k]>0&&arr[k]<=sqrt(i))

{

if (i%arr[k] == 0)

{

break;

}

k++;

}

if (!arr[k]||(arr[k] > sqrt(i)))

{

printf("%d\t", i);

arr[j] = i;

j++;

}

}

}

int main()

{

int num;

printf("请输入一个正整数:");

scanf("%d",&num);

if (num > 1)

{

printf("打印出所有的素数:");

print_prime(num);

}

else

{

printf("不存在小于等于%d的素数",num);

}

printf("\n");

return 0;

}

方法二:筛选法

这种方法求素数的思想就是,不断筛去最小的数的倍数。这个最小的数必然是素数。

比如最小的素数是2,去掉所有2的倍数;接下来最小的数是3,3就是素数,去掉所有的3的倍数;依次类推,直到最小的数小于等于√n为止。为什么是√n呢? 在上面的试除法中讲到只要试除小于等于√n的所有素数即可判断出小于等于n的所有素数,这里同样适用,只要去掉所有的小于等于√n的所有数的倍数,剩下的数就是小于等于n的所有素数。

代码如下:

#include

#include

#define MAX 1000  //定义数组的大小

int print_prime(int num)//prime表示素数

{

int arr[MAX] ;

int i = 0,j=0;

for (i = 0; i < num - 2; i++)//初始化数组[2,num]

{

arr[i] = i + 2;

}

while (arr[j]<=sqrt(num))//除数的范围

{

for (i = j + 1; i < num - 1; i++)

{

if (arr[i]%arr[j] ==0)//筛去arr[i]的倍数

{

arr[i] = 0;

}

}

j++;

while(!arr[j])//确定最小数

{

j++;

}

}

for (i = 0; i < num - 1; i++)

{

if (arr[i])

{

printf("%d\t",arr[i]);

}

}

}

int main()

{

int num;

printf("请输入一个正整数:");

scanf("%d",&num);

if (num > 1)

{

printf("打印出所有的素数:");

print_prime(num);

}

else

{

printf("不存在小于等于%d的素数",num);

}

printf("\n");

return 0;

}

上面的代码有一个很明显的缺陷就是开辟空间过大,如何来解决这个问题呢?

上述代码所开辟的空间为int型,占用4个字节,占用空间太多,可以构造一个bool型数组,bool型是一个基本的数据类型,占1个字节,以下标来存储数据,节省了75%的空间。

优化:

构造bool型数组,以下标来存储数据,每个数只占一个字节。

代码如下:

#include

#include

#include

#define MAX 1000  //定义数组的大小

void print_prime(int num)//prime表示素数

{

bool arr[MAX] ;

int i = 0,j=2;

for (i = 0; i

{

arr[i] = 1;

}

while (arr[j]<=sqrt(num))//除数的范围

{

for (i = j + 1; i <= num ; i++)

{

if (i%j ==0)//筛去arr[i]的倍数

{

arr[i] = 0;

}

}

j++;

while(!arr[j])//确定最小数

{

j++;

}

}

for (i = 2; i <=num ; i++)//打印素数

{

if (arr[i])

{

printf("%d\t",i);

}

}

}

int main()

{

int num;

printf("请输入一个正整数:");

scanf("%d",&num);

if (num > 1)

{

printf("打印出所有的素数:");

print_prime(num);

}

else

{

printf("不存在小于等于%d的素数",num);

}

printf("\n");

return 0;

}

结果1:

请输入一个正整数:9

打印出所有的素数:2     3       5       7

请按任意键继续. . .

结果2:

请输入一个正整数:1

不存在小于等于1的素数

请按任意键继续. . .

### 回答1: 对于这个问题,我可以提供以下策略:首先,使用穷举法,用一个for循环,从2开始遍历到n,每次判断一个数是否为素数,使用一个for循环,从2开始到这个数的平方根,每次判断这个数是否能被i(2到数的平方根)整除,如果能,则不是素数,如果不能,则是素数输出每个素数,每行输出10个素数。 ### 回答2: 设计C语言程序,输出所有小于等于n的素数实现步骤如下: 1. 定义函数is_prime(n),用于判断一个数n是否为素数。判断方法为:若n为2或3,则返回1;若n能被2或3整除,则返回0;否则,从5开始,判断n是否能被5及其之后的奇数整除,若能则返回0,若不能则返回1。 2. 在主函数中,接收用户输入的大于2的正整数n。 3. 定义计数器count,用于记录每行已输出素数个数。 4. 使用循环从2开始遍历至n,对于每个数字i,判断是否为素数。 5. 如果是素数,则输出该数字,并将count加1。 6. 判断count的值,若count为10,则输出换行符,并将count重置为0。 7. 循环直到遍历完所有数字。 优化算法: 1. 从5开始,只需要判断奇数是否能整除,因为偶数可以被2整除。 2. 对于每个数字i,我们只需要判断其是否能被小于根号i的素数整除。因为,如果存在大于根号i的素数p,将i除以p后得到的商q一定小于根号i,所以我们只需要判断小于根号i的素数是否能整除i即可。 3. 使用一个数组prime[]存储已经判断素数,初始时数组为空。在判断一个数字i是否为素数时,只需要使用prime[]中的元素去除i即可,无需使用所有小于i的数字。 下面是优化后的C语言程序示例: ```c #include <stdio.h> #include <math.h> int is_prime(int n) { if (n == 2 || n == 3) { return 1; } if (n % 2 == 0 || n % 3 == 0) { return 0; } int i = 5; int w = 2; while (i * i <= n) { if (n % i == 0) { return 0; } i += w; w = 6 - w; // 在2和4之间切换,优化循环次数 } return 1; } int main() { int n; printf("请输入一个大于2的正整数n:"); scanf("%d", &n); int count = 0; for (int i = 2; i <= n; i++) { if (is_prime(i)) { printf("%d\t", i); count++; if (count == 10) { printf("\n"); count = 0; } } } printf("\n"); return 0; } ``` 该程序使用了较优的算法,能够高效地输出所有小于等于n的素数,且每行输出10个素数。 ### 回答3: 要设计一个C语言程序,输出所有小于等于给定正整数n的素数,满足以下要求: 1. 在程序中定义一个函数isPrime(num),该函数用于判断一个数是否是素数素数是指只能被1和自身整除的数。该函数返回值为1表示是素数,返回值为0表示不是素数。 2. 主函数中定义变量count和lineCount,分别用于计数当前已输出素数的数量和当前行已输出素数的数量。 3. 使用for循环从2开始遍历到n,每次判断当前数是否是素数,如果是素数则进行打印输出。同时更新count和lineCount的值。每次输出10个素数后换行。 4. 在isPrime函数中,使用for循环从2开始遍历到num的平方根,判断该数是否能整除num。如果能整除,则不是素数,返回0;否则,继续循环。如果循环结束仍然没有找到可以整除num的数,则说明num是素数,返回1。 以下是相应的C语言代码示例: ```c #include <stdio.h> #include <math.h> int isPrime(int num) { int i; for (i = 2; i <= sqrt(num); i++) { if (num % i == 0) { return 0; } } return 1; } int main() { int n, count = 0, lineCount = 0; printf("请输入一个大于2的正整数:"); scanf("%d", &n); printf("小于等于%d的素数有:\n", n); for (int i = 2; i <= n; i++) { if (isPrime(i)) { count++; lineCount++; printf("%d ", i); if (lineCount % 10 == 0) { printf("\n"); } } } printf("\n共有%d个素数。\n", count); return 0; } ``` 以上代码通过定义一个isPrime函数,使用了较优的算法来判断是否为素数。主函数中使用for循环遍历所有小于等于n的数,并在每行输出10个素数后换行。最后输出总共有多少个素数
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值