程序猿进化史——质数再练习

两个程序写了3个多小时,时间基本都花在查资料,Debug上。Java用法不熟悉,一些数学函数(Java中称数学方法更合适?)的使用,比如开根号,求ln,都是直接在网上查的;

改进定义的方法已经写了3遍了,感觉还是不是很溜。特别是对于isPrime放在哪里迷迷糊糊,嵌套for循环感觉让思路很混乱。自己写了一遍流程图才稍微明朗点,果然是智商不够用么。。。

筛选法第一次写。这次先写了流程图,果然在写程序的时候思路清晰很多。不过,写完第一遍各种数组越界,除数中有零,本质都是数组下标的运算不严紧敲打。。。幸好Java能提示越界,要是C的话,估计又要自己Debug半天(还未必能看出来快哭了)。。。。对于这些细节在写的时候确实没有考虑进去,需要下标运算的时候,就把数组范围和对应的下标注释出来。

基本都是在处理越界问题,最后实在Debug不出来了,只能重新梳理流程和各部分功能,逐个验证功能的正确性。。。(没有函数不习惯。。。)

还是欠练!

筛选法中,估计质数个数有误差,可能是数据太少;所以没有输出所有质数,只是做了统计。


package test;
import java.util.Scanner;
public class test {

	public static void main(String[] args) {
		/*1、改进定义方法:
		*遍历所有奇数,偶数不可能是质数(2除外)
		*判断n是否是质数:求n / (2 to sqrt(n)) == 0 
		* n = sqrt(n) * sqrt(n) ,所以只到sqrt(n)就行
	*/	
	//-----改进定义方法------------------------------
		System.out.println("Input n: ");
		Scanner scanf = new Scanner(System.in);
		int n = scanf.nextInt();
		int count = 1;			//质数的个数;
		System.out.println("2");
		boolean isPrime = true;
		int j;
		//int sqr = (int)(Math.sqrt(n));
		for(j=3; j<=n; j+=2){		//3-n中的奇数;
			for(int i=2; i<=(int)(Math.sqrt(n)); i++){		//遍历2 to sqr(n)
				if(j%i==0 && j!=i){
					isPrime = false;
					break;
				}
			}
			if(isPrime){
				count++;
				System.out.println(j);
			}
			isPrime = true;
		}
		System.out.println("The count is: ");
		System.out.println(count);
	}  //class ends
}

package Prime;
import java.util.Scanner;

public class IsPrime{
	public static void main(String[] args){
	/*----2. 埃拉托斯特尼筛法-----------------
	* 在[2,n]的序列中,逐步剔除所有质数的倍数;
	* 如果剔除后的数列中最大数小于当前素数的平方,则继续剔除;
	* Step: 1. 数列[2, 3, 4, 5, ..., 25];
			2. 剔除2的倍数,得到[2,3,5,7,...,23,25];
			3. 2中数列的最大数是25,小于当前素数2的平方,则继续执行2;
			4. 2后面最小的是3,所以3是质数。。。
			5. 直到当前剔除素数的平方大于数列中的最后一个数,则完成。
	* 构造数组arr,储存[2,n]所有数据;
	* 将剔除的数据置0;
	* 数组primeNum存储[2,n]所有的质数;
	* 确定primeNum的长度:素数定理:确定某个范围内的素数个数:误差15%
		len = x/ln(x), x = n;
		len = len * 1.15;	(一般扩大15%范围)
	* 确定下一个素数:最近一个不为0的数;
	* 确定当前数列最后一个数:从数组最后开始遍历,第一个不为0的数;
	*/
	
	int n = 200;
	int[] arr = new int[n-1];	//储存2-n所有数;
	
	//生成arr数组: [2, n];
	for(int i=0; i<=n-2; i++){
		arr[i] = i+2;
		System.out.print(arr[i]+"  ");
		
	}	
		
	System.out.println();
	//剔除倍数:
	int curPrime = 2;					//当前质数;
	int maxOfArr = arr[n-2];			//当前数组中的最大数;
	int maxIndex = arr.length-1;		//当前最大数的下标
	int t = curPrime;
	int next = 1;					//下一个非0的数的下标;
	int count = 0;					//需要剔除count次才能得到所有素数;
	
	//剔除素数的倍数;
	do{
		t = curPrime;
		//剔除curPrime的倍数;
		for(int i=next; i<=maxIndex; i++){
			if(arr[i]%curPrime == 0){
				arr[i] = 0;
			}
		}
		//求当前数组的最大数和其下标: 最后一个非0的数;
		for(int i=maxIndex; i>=0; i--){
			if(arr[i] != 0){
				maxIndex = i;
				maxOfArr = arr[i];
			}
		}
		
		//print the result
		for(int i=0; i<=n-2; i++){
			System.out.print(arr[i]+"  ");
		}	
		System.out.println();					//每次剔除都输出;
	}while(maxOfArr >= t*t);
	
	}//class ends;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值