素数

本文介绍了素数的基本概念及两种常见的素数计算方法:试除法和筛选法,并提供了相应的Java实现代码。试除法适用于小范围内的素数计算,而筛选法则更适用于大规模的素数寻找任务。



1.素数定义

  只能被1和它自己整除的自然数称为素数,特别规定1不属于素数。

2.素数的判断方法
  (1)根据素数的定义,很明显,如果一个数是素数<==>它的因子只包含1和它本身。

      因此可以根据判别某个数的因子的方法来判断其是否是素数。 

public class Prime {

	public static void main(String[] args) {
	   int n=0;
	   System.out.println("以下是1~100自然数中依次出现的指数:");
       for(int i=2;i<=100;i++){
    	   if(isPrime(i)){
    		   n++;
    		   System.out.print(i+"\t");
    		   if(n%10==0){
    			   System.out.println();
    		   }
    	   }
       }
       System.out.println();
       System.out.println("1~100自然数中质数的个数为:"+n);
		
	}

	
    private static boolean isPrime(Integer num){
    	for(int i=2;i<=Math.sqrt(num);i++){
    		if(num%i==0){
    			return false;
    		}
    	}
    	return true;
    }
}

注:上面的做法是基本的做法。也可说:以时间换空间


(2)但是如果要求求出1000000以内的所有素数,上面的方法效率就很低,因此通常采用筛选法去求素数。

      筛选法:对于一个数n,如果是素数,那么2*n,3*n,4*n,必定不是素数。

import java.util.Arrays; 
public class FilterPrime {
	 /* 
     * **求N以内的质数 
     */  
    Integer N;  
    FilterPrime(int inputN){  
        this.N = inputN;  
    }  
	//筛选法  
    private boolean[] filterNumber(int num){  
        if(num<=0){  
            System.out.println("范围必须大于0");  
            return null;  
        }  
        boolean[] isPrime = new boolean[num + 1];  
        isPrime[1] = false;  
        Arrays.fill(isPrime,2,num,true);  
        int n = (int)Math.sqrt(num);  
        for(int i=1;i<n;i++){  
            if(isPrime[i]){  
                for(int j=2*i;j<=num;j+=i){  
                    isPrime[j]= false;  
                }  
            }  
        }  
        return isPrime;  
    }  
    private void getResult(){
        boolean[] primes= filterNumber(N);  
        int num=0;  
        if(primes!=null){  
            for(int i=1;i<primes.length;i++){  
                if(primes[i]){  
                    System.out.println(i+" ");  
                    if(++num%10==0)  
                        System.out.println();  
                }  
            }  
            System.out.println();  
        }  
        System.out.println("一共有"+num+"个质数");  
          
    }  
    public static void main(String[] argc){  
    	FilterPrime prime = new FilterPrime(100000);  
        prime.getResult();  
    }  
}

注:上面是以空间换时间的做法。


明白了!你说的“不是质数素数”,应该是说: > 判断一个数是否是**素数质数)**,而不是合数。 我们来重新梳理一下你的原始代码意图: 你希望判断一个数是否是**素数**(即质数),而你的函数 `haha` 实际上是判断一个数是否是**合数**(非质数),所以逻辑是反的。 --- ## ✅ 正确判断素数的函数(优化版) ```c #include <stdio.h> #include <stdbool.h> #include <math.h> // 判断一个数是否为素数 bool is_prime(int a) { if (a < 2) return false; // 0和1都不是素数 int sqrt_a = (int)sqrt(a); // 只需要检查到平方根即可 for (int i = 2; i <= sqrt_a; i++) { if (a % i == 0) return false; // 能整除则不是素数 } return true; } ``` > **说明**: - 时间复杂度从原来的 `O(a/2)` 优化到 `O(√a)`。 - 更加高效,尤其在处理大数时提升明显。 --- ## ✅ 修正主函数逻辑 你原来的主函数中,有一个 `while(k--)` 的写法是错误的,因为 `k` 是在循环中被递减的,导致第一次循环后 `k` 就变成 0,后续循环无法再进入。 我们来修正整个逻辑,使用**滑动窗口**或**前缀和**来高效地处理连续 `k` 个元素的和。 ### ✅ 改进后的完整代码 ```c #include <stdio.h> #include <stdbool.h> #include <math.h> bool is_prime(int a) { if (a < 2) return false; int sqrt_a = (int)sqrt(a); for (int i = 2; i <= sqrt_a; i++) { if (a % i == 0) return false; } return true; } int main() { int n, k; scanf("%d%d", &n, &k); int a[n]; // 输入数组 for (int i = 0; i < n; i++) { scanf("%d", &a[i]); } int count = 0; // 对每个起点 i,计算连续 k 个元素的和(循环数组) for (int i = 0; i < n; i++) { int sum = 0; for (int j = 0; j < k; j++) { int index = (i + j) % n; // 循环取数 sum += a[index]; } if (is_prime(sum)) { count++; } } printf("%d\n", count); return 0; } ``` > **说明**: - `is_prime` 函数用于判断和是否是素数。 - 每次从位置 `i` 开始,取 `k` 个元素(循环数组),求和后判断是否为素数。 - 总时间复杂度为 `O(n * k + n * √sum)`,在合理范围内。 --- ## ✅ 示例 输入: ``` 5 2 2 3 5 7 11 ``` 输出: ``` 5 ``` 说明:所有连续两个数的和都是素数。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值