参考文章:http://blog.csdn.net/kp_liu/article/details/37569507

http://blog.csdn.net/huang_miao_xin/article/details/51331710

https://www.zybang.com/question/93c4703c84c5ad3c1c34b1e6672b0568.html

素 数

——只能被1和它本身整除的数(除1以外,1既不是素数也不是合数)

              • 现给出一个数N(N为正整数),编写方法判断其是否为素数。

直观想法

遍历从2至N-1,看是否存在N的约数。若存在,即不是素数。

基础改进

不必从2遍历至N-1,数N若是合数,则其至少可由两个因数相乘得到,这两个数必定一个大于(或等于)sqrt(n),一个小于(或等于)sqrt(n),因此仅需遍历至sqrt(n)即可。

改进方法一 (偶数;缩小判断范围;)

Step 1 (除2以外)判断N是否为偶数,若是,则判断结束——不是素数;

Step 2  若N不是偶数但是合数,它的因数绝不可能是偶数(原因 偶数×偶数=偶数;偶数×奇数=偶数),

因此判断奇数N的因数时,可以省去对偶数的判断。(i+=2)

 static boolean isPrime_1(int N){
int tmp=(int)Math.sqrt(N);
//Step 1
if(N==2)return true;
if(N%2==0)return false;
//Step 2
for(int i=3;i<tmp;i+=2)
if(N%i==0)return false; return true;
}

改进方法二 (质数分布规律;pruning策略;)

一个关于质数分布的规律:大于等于5的质数一定和6的倍数相邻(即大于等于5的质数x,都可以表示为x=6k+1 或者是 x=6k-1,k为>0的自然数)。

但要注意:在6的倍数相邻两侧并不是一定就是质数。

证明

直观看,大于等于5的自然数都可以用6k-1,6k,6k+1,6k+2,6k+3,6k+4,6k+5的形式表示,显然6k+2 = 2(3k+2),6k+3 = 3(2k+1),6k+4 = 2(3k+2)都是合数,再除去6k本身,因此大于等于5的质数都可以表示成6k+1和6k+5(当x大于等于6时,6k+5与6k-1可表示同一个数)的形式。

数学证明

  • 质数x大于等于5,则一定不是3的倍数,也不是2的倍数。
  • 如果一个自然数不是3的倍数,有两种情况,设 x=3p+1或x=3p+2 (p>1)
  • 如果一个自然数不是2的倍数,有一种情况,设 x=2t+1 (t>3)

1)若x=3p+1,且x=2t+1

则x=3p+1=2t+1 >> x-1=3p=2t

>> 3p=2t,可知p为2的倍数,t为3的倍数,

设p=2k,>> t=3k

因此x=2*3k+1=6k+1

2)若x=3p+2,且x=2t+1

则x=3p+2=2t+1

>> 3p+1=2t,因此3p为奇数,即p为奇数,设p=2k-1

则3*(2k-1)+1=2t,>> t=3k-1

因此x=2(3k-1)+1=6k-1

Step 1  单独判断2、3,都是素数;

Step 2  判断N是否在6的倍数的两侧,若不在,则判断结束——不是素数;

Step 3  数N在6的倍数两侧也不一定是质数,还需判断是否能在6的倍数两侧的数中找到数N的因数,若找不到,才可判定为质数。

(为什么只需在“6的倍数两侧的数”中寻找因数?

原因 所有合数可由质数的积组成,所以N只需要与可能是质数(即6的倍数的前后两个数)的数进行取余)

 static boolean isPrime_2(int N){
int tmp=(int)Math.sqrt(N);
//Step 1
if(N==2||N==3)return true;
//Step 2
if(N%6!=1&&N%6!=5)return false;
//Step 3
for(int i=5;i<=tmp;i+=6)
if(N%i==0||N%(i+2)==0)return false;
/*此处
* i表示形式为6k+5的数,
* i+2表示形式为6k+1的数
*/ return true;
}

方法比较 && 代码测试

测试代码

数据情况

              • “改进方法二” 完胜

E N D

算法改进 | java语言中判断素数的更多相关文章

  1. JAVA语言中冒号的用法

    近来由于本人要介入android平台的开发,所以就买了本JAVA语言的书学习.学习一段时间来,我的感觉是谭浩强就是厉害,编写的<C编程语言>系列丛书不愧是经典.书中对C语言的介绍既系统又全 ...

  2. Java语言中的正则表达式

    正则表达式是什么? 正则表达式是一种强大而灵活的文本处理工具.初学正则表达式时,其语法是一个难点,但它确实是一种简洁.动态的语言.正则表达式提供了一种完全通用的方式,能够解决各种字符串处理相关的问题: ...

  3. 深度实战玩转算法, Java语言7个经典应用诠释算法精髓

    深度实战玩转算法,以Java语言主讲,通过7款经典好玩游戏,真正将算法用于实际开发,由算法大牛ACM亚洲区奖牌获得者liuyubobobo主讲,看得见的算法,带领你进入一个不一样的算法世界,本套课程共 ...

  4. JAVA语言中的修饰符

    JAVA语言中的修饰符 -----------------------------------------------01--------------------------------------- ...

  5. Java语言中的面向对象特性总结

    Java语言中的面向对象特性 (总结得不错) [课前思考]  1. 什么是对象?什么是类?什么是包?什么是接口?什么是内部类?  2. 面向对象编程的特性有哪三个?它们各自又有哪些特性?  3. 你知 ...

  6. Java语言中的面向对象特性:封装、继承、多态,面向对象的基本思想(总结得不错)

    Java语言中的面向对象特性(总结得不错) [课前思考] 1. 什么是对象?什么是类?什么是包?什么是接口?什么是内部类? 2. 面向对象编程的特性有哪三个?它们各自又有哪些特性? 3. 你知道jav ...

  7. Java语言中的异常处理

    Java语言中的异常处理包括声明异常.抛出异常.捕获异常和处理异常四个环节.   throw用于抛出异常.   throws关键字可以在方法上声明该方法要抛出的异常,然后在方法内部通过throw抛出异 ...

  8. 列举java语言中反射的常用方法

    package review;/*12:43 2019/7/21*/ import model.AnotherClass; import model.OneClassMore; import mode ...

  9. Java语言中使用OpenMP

    从去年年中,开始学习Java,主要是维护公司用Java编写的服务器软件.目前,该服务器软件遇到一个问题,在下载大文件时,如果同时下载的用户很多, 服务器软件工作会出现异常,有的用户无法下载.服务器硬件 ...

随机推荐

  1. python webdriver 环境搭建详解

    学了一个月用java编写selenium driver 测试脚本,也将公司做的系统基本可用的模块做了一次自动化,虽然写的比较简陋,但是基本可用跑一遍,并用testNG生成了测试报告. 学习方式无非是: ...

  2. 编译安装Nginx到Linux

    之前安装的H2O不知道为啥,总是崩溃,换Nginx了下载包:http://nginx.org/download/ 配置:./configure --prefix=/usr/local/nginx -- ...

  3. 保存数据到sdcard中去

    这里只贴上核心的代码:其它自行脑补!

  4. idea启动tomcat报错:Error during artifact deployment. See server log for details.

    出现这种情况的原因老夫猜想是改变了artifact然而tomcat的配置中的artifact没有重新配就会出现这种报错 打开tomcat配置 删除原来的artifact 新添加artifact 保存 ...

  5. epoll的ET和LT两种模式对比及注意事项

    ET模式: 因为ET模式只有从unavailable到available才会触发,所以 1.读事件:需要使用while循环读取完,一般是读到EAGAIN,也可以读到返回值小于缓冲区大小: 如果应用层读 ...

  6. 【Kafka】

    KafkaProducer Kafka消息发布客户端. 线程安全,跨线程共享单个生产者实例通常比拥有多个实例的速度更快. 例子,使用生产者发送包含序列号的字符串作为键/值对的记录: Propertie ...

  7. 基于MyBatis3.0.6的基本操作介绍

    每 一 个 MyBatis 的 应 用 程 序 都 以 一 个 SqlSessionFactory 对 象 的 实 例 为 核 心 .SqlSessionFactory本身是由SqlSessionFa ...

  8. thinkphp增删改查

    添加数据: (添加单行数据) // 添加成功返回1,失败返回0 (添加多行数据) // 返回添加数据的条数 删除数据: 修改数据: (修改单个字段) (修改多个字段) // 修改成功返回1,失败返回0 ...

  9. 跨平台的 NodeJS 组件解决 .NetCore 不支持 System.Drawing图形功能的若干问题

    问题 生成缩略图 生成验证码 生成二维码 给图片加水印 外部引用 Node  不解释  https://nodejs.org/en/download/ sharp 高性能缩略图  https://gi ...

  10. Linux向文件添加内容的几种方法

    例如,要想test.txt文件添加内容"I am a boy",test.txt在当前目录中 方法一:vi编辑法 打开终端,输入vi test.txt 回车,按a或i进入编辑模式, ...