总目录
除了数字和这个数本身,没有其他约数的数,就是质数。另外规定1不是质数,而2是。
关于这个1不是素数的规定,就是质因数分解时,可以有唯一的一种写法,这也是如下定理规定的
将正整数分解成多个素数乘积的方法只有一种
当然这不是本文章的重点,本篇文章主要是想把在指定范围内的素数全部求解出来,而且使用Stream类,以及不用for、while语句。
private void getPrimeNumber() {
int value = 100;// 在100以内查找全部素数
int[] array = IntStream.iterate(2, v -> v + 1)// 因为素数从2开始,所以生成2,3,4……这样的数列
.limit(value - 1)// 只生成99个,因为是从2开始,生成第100个时的,数字就是101了
.filter(v -> {// 核心逻辑判断代码,返回条件为真的数,才是素数
if (v == 2) return true;// 如果2,为素数
if (v % 2 == 0) return false;// 全部双数,都不是素数
return !(IntStream.iterate(3, v1 -> v1 + 2)// 生成单数数列
.limit(Double.valueOf(Math.sqrt(v)).intValue())// 单数数列范围
.anyMatch(v1 -> v != v1 && v % v1 == 0));// 发现可以整除,就不是素数
}).toArray();
System.out.println(Arrays.toString(array));// 打印一下生成的素数数列
System.out.println(array.length);
}
-
filter
筛选素数的代码比较复杂,详细说明一下 - 第7行代码,首先将全部双数筛选出去
- 接下来就是从单数中找约数
- 第8行开始,生成单数数列,从3开始,形如3,5, 7……这样的数列
- 第9行,是限制数列的范围,就是到这个数的开根号的值的整数部分,比如看一下15是不是素数,用生成的只含有两个元素的数列3和5,与15相除是不是不含余数(即整除),而这里的数字5,是来自15开根号后,取值中的整数
-
anyMatch
这个函数,只要发现一个可以整除,且不是这个数本身的数,就返回(对数字5,判断它是不是素数,先生成单数数列,是从3开始,而5开根号的值取整的话,就是2,那么最终生成的数列有两个值,3和5,而5可以整除5,会判断出5不是素数的错误,所以要加上v1不等于v的条件 - 没有for、while语句,不错啊!
以上代码可以求解数值较小范围内数字中的素数,范围大一些的话,效率会不好,但也可以加入parallel()来使用并行计算。但更有效的算法是使用埃拉托色尼筛选法,是先把一些基本素数筛选出来,然后在一定范围内,把这些素数的倍数去掉,剩下的就是素数了,这篇文章会依据这个算法再出一个补丁,把这个算法也囊括进来。