[原创]求质数 之 除余法(C语言描述)

问题描述

试编写一个程序,找出 2→N 之间的所有质数(质数的概念请看这里

),用尽可能快的方法实现。

问题分析

这个问题可以有两种解法:一种是用“筛子法”,另一种是从 2→N 逐一检测出质数。如果要了解“筛法”,请看另一篇文章《求质数 之 筛法

》。

现在来介绍第二种方法。用这种方法,最先想到的就是让从2→N逐一检查。如果是就显示出来,如果不是,就继续检查下一个直到超出范围 N。这是正确的做法,但效率却不高。当然,2 是质数,那么 2 的倍数就不是质数,如果令 i 从 2→

N,就很冤枉地测试了 4、6、8……这些数?所以第一点改建就是只测试 2 与所有的奇数就足够了。同理,3 是质数,但6、9、12……这些 3 的倍数却不是,因此,如果能够把 2 与 3 的倍数跳过去而不测试,任意连续的 6 个数中,就只会测试 2 个而已。以6n, 6n+1, 6n+2, 6n+3, 6n+4, 6n+5 为例,6n, 6n+2, 6n+4 是偶数,又 6n+3 是 3 的倍数,所以如果 2 与 3 的倍数都不理会,只要测试的数就只留下6n+1和6n+5而已了,因而工作量只是前面想法的 2/6 = 1/3,应该用这个方法编程。

还有个问题,就是如果判断一个数 i 是否为素数。按素数的定义,也就是只有 1 与本身可以整除,所以可以用 2→

i-1 去除 i,如果都除不尽,i 就是素数。观点对,但却与上一点一样的笨拙。当 i>2 时,有哪一个数可以被 i-1 除尽的?没有!为什么?如果 i 不是质数,那么 i=a×b,此地 a 与 b 既不是 i 又不是 1;正因为 a>1,a 至少为 2,因此 b 最多也是 i/2 而已,去除 i 的数用不着是 2→

i-1,而用 2→

i/2 就可以了。不但如此,因为 i=a×b,a 与 b 不能大于 sqrt(i),为什么呢?如果 a>sqrt(i),b>sqrt(i),于是 a×b > sqrt(i)*sqrt(i) = i,因此就都不能整除i了。如果i不是质数,它的因子最大就是 sqrt(i);换言之,用 2→

sqrt(i)去检验就行了。

但是,用 2→

sqrt(i) 去检验也是浪费。就像前面一样,2 除不尽,2 的倍数也除不尽;同理,3 除不尽,3 的倍数也除不尽……最理想的方法就是用质数去除i。

但问题是这些素数从何而来?这比较简单,可以准备一个数组 prime[],用来存放找到的素数,一开始它里面有 2、3、5。检查的时候,就用 prime[] 中小于 sqrt(i)的数去除 i 即可,如果都除不尽,i 就是素数,把它放如 prime[] 中,因此 prime[] 中的素数会越来越多,直到满足个数为止!

不妨用这段说明来编写这个程序,但是程序设计的时候会有两个小问题:

  1. 如果只检查 6n+1 和 6n+5 ?不难发现,它们的距离是4、2、4、2……所以,可以先定义一个变量 gab=4,然后 gab=6-gab;
  2. 比较是不能用 sqrt(i),因为它不精确。举个例子,i=121,在数学上,sqrt(i) 自然是 11,但计算机里的结果可能是 10.9999999,于是去除的数就是 2、3、5、7,而不含 11,因此 121 就变成质数了。解决这个问题的方法很简单,不要用开方,用平方即可。例如,如果 p*p<=i,则就用 p 去除 i。而且它的效率比开方高。

程序清单

#include <stdlib.h>
#include <stdio.h>
int creat_prime(int p[], int n, int total)
{
int i, j, g = 2;
for (i = 7; i <= n; i += g) {
g = 6 - g;
for (j = 0; p[j] * p[j] <= i && i % p[j]; j++);
if (i % p[j]) {
p[total++] = i;
}
}
return total;
}
int main(void)
{
int prime[30000] = { 2, 3, 5 };
int total = 3; /* 找到素数的个数 */
int n = 200000; /* 要查找的范围(>=6) */
int i;
total = creat_prime ( prime, n, total );
for (i = 0; i < total; i++) {
printf ( "%d ", prime[i] );
if ( i && !(i % 10) )
putchar ( '/n' );
}
putchar ( '/n' );
return EXIT_SUCCESS;
}


版权声明

本人的所有原创文章皆保留版权,请尊重原创作品。

转载必须包含本声明,保持本文完整,并以超链接形式注明原始作者“redraiment

”和主站点

上的本文原始地址。

联系方式

我的邮箱,欢迎来信(redraiment@gmail.com

我的Blogger(子清行

我的Google Sites(子清行

我的CSDN博客(梦婷轩

我的百度空间(梦婷轩

时间: 2024-08-31 13:02:24

[原创]求质数 之 除余法(C语言描述)的相关文章

[原创]求质数 之 筛法(C语言描述)

问题描述 试编写一个程序,找出 2→N 之间的所有质数(质数的概念请看这里),用尽可能快的方法实现. 问题分析 这个问题可以有两种解法:一种是用"筛子法",另一种是从 2→N 逐一检测出质数.如果要了解"除余法",请看另一篇文章<求质数 之 除余法>. 先通过一个简单的例子来介绍一下"筛法",求 2→20 的质数,它的做法是先把 2→20 这些数一字排开: 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17

素数-求质数并打印,下面是我的写法,求改进,求其他写法

问题描述 求质数并打印,下面是我的写法,求改进,求其他写法 package test; import java.util.Scanner; public class TestPrime { public static void main(String[] args) { Scanner sc=new Scanner(System.in); System.out.println("请输入一个整数"); int num=sc.nextInt(); System.out.println(&q

算法练习:求质数

题目:求质数 内容: 试编写一个程序,找出前N个质数.如果没有进一步要求,这不是难题.但在此希望从所知的.使用除法的方法中,用最快的办法来编写程序. 我的解法:上来没多想,打开vs2013就敲了起来,问题果然很简单,分分钟就超神..奥,不对就解决了!这个题目确实很简单,先看看常规解法吧! #include <iostream> #include <math.h> #define endNum 200 using namespace std; int _tmain(int argc,

c语言-如何写一个求质数的C语言程序,带注释的,自己做了很久都有问题,老师讲也没听懂。

问题描述 如何写一个求质数的C语言程序,带注释的,自己做了很久都有问题,老师讲也没听懂. 如何写一个求质数的C语言程序?求大神帮帮忙,带注释 //,谢谢了 新人求助. 解决方案 /*求素数的三种方法 一:for(i=2;i<=(n-1);i++) if(n%i==0)i在2到n-1之间任取一个数如果n能被整除则不是素数,否则就是素数 二:for(i=2;i<n/2;i++) if(n%i==0) /*i在2到n/2之间任取一个数如果n能被整除则不是素数,否则就是素数 三:for(i=2;i&l

c++-C++求质数程序求助.....

问题描述 C++求质数程序求助..... 题目. 判断101-200之间有多少个素数,并输出所有素数. 程序如下: #include using namespace std; int main() { int i,j,l,t; t=0; cout<<"范围内质数如下:"< for(i=101;i100;i++) { l=1; for(j=2;j<=(i/j+1);j++) { if(i%j==0) { l=0; break; } } if (l) { cout&

老师 ,java 程序题目 求 质数 比如 90 输出 2 3 3 5

问题描述 老师 ,java 程序题目 求 质数 比如 90 输出 2 3 3 5 我 写 的程序 ,老师 指导 指导 , 运行报错,调试 也调试不了 package com.imocc; public class Practice{ int user; public void get(int x){ if((x==1)||(x==5)||(x==7)||(x==3)){ System.out.println(x); return; } for( int i=2;i<x;x++){ if(x%i=

编译器-小白求助,求质数程序死循环

问题描述 小白求助,求质数程序死循环 for i in range(1,10000): for n in range(1, (i - 1)): if ( (i % n) != 0): print i 解决方案 import math def isPrime(n): if n <= 1: return False for i in range(2,int(math.sqrt(n))+1): if n%i == 0: return False return True def hasPrime(n):

增删改查-求大神解决啊 用c语言

问题描述 求大神解决啊 用c语言 1.使用结构体保存学生信息,学生信息包含学号,姓名,性别,班级,语文成绩,数学成绩 2.用户可以进行学生信息的增删改查,要求使用switch为用户提供增删该查选项 3.在主函数中提供增删改查选项,使用函数完成增删该查具体功能 解决方案 http://zhidao.baidu.com/link?url=sOPqZ98X7FdSx7mCX12eUkiaaPIHPQe1GWfzrfU-QAwX0NWcXXfFEDu8vu25MftOxlmdqXMvFoNoPCVZ_R

c语言基础-真的很着急,大一学生党,求大神指导写一个c语言拨号程序

问题描述 真的很着急,大一学生党,求大神指导写一个c语言拨号程序 能显示出通讯录中所有人姓名,当选中某个姓名时,屏幕上模拟打字机效果依次显示出此人的电话号码中的各个数字,并伴随相应的拨号声 解决方案 http://zhidao.baidu.com/link?url=svF4fjRTNuBmCJyCiRipzB_21UO5zvNc0hCye7qj8nxOY1lC78667ycDqYnJ7xHiGT00M4NuYqGIak2R5cEU961mjRl1ADLf-Eh1nDKpiBi