一、目的 {#一目的}

掌握JDK安装与配置,掌握Java IDE开发环境配置与基本使用。

二、实验内容与设计思想 {#二实验内容与设计思想}

设计思路 {#设计思路}

  1. 熟悉控制台下常用命令
  2. JDK的配置与HelloWorld
  3. eclipse/intellij idea安装与使用
  4. 筛法求素数
  5. 最大公约数
  6. 求e的近似值

主要代码结构

筛法求素数

最大公约数

求e的近似值

主要代码段分析

  • 埃氏筛法代码段:
for (int i = 2; i <= n; i++) {
			if (arr[i] == 0) {
				result[index++] = i;
			}
			for (int j = 2 * i; j <= n; j += i) {
				arr[j] = 1;
			}
		}

埃氏筛法的想法是筛掉当前i的倍数直到上界,则一定能判断到下一个i是否为素数。

问题是多次重复筛选造成效率地下。


  • 欧氏筛法代码段:
for (int i = 2; i <= n; i++) {
			if (arr[i] == 0)
				result[index++] = i;
			for (int j = 0; j < index && i * result[j] <= n; j++) {
				arr[i * result[j]] = 1;
				if (i % result[j] == 0) {
					break;
				}
			}
		}

除了埃式筛法中的arr数组,我们还要维护一个集合,里面用来存放已知的质数。

埃式筛法中,当前数为质数时,才进行下面的操作。而欧式筛法,对每一个数都进行操作。

对于当前数来说,把它依次和集合中的质数相乘,得到的数必为合数,然后筛掉。但是当当前数可以整除当前的质数时,结束循环。


三、实验使用环境 {#三实验使用环境}

软件:java version “18.0.2”
EclipseIDE 2022-06
平台:win10

四、实验步骤和调试过程 {#四实验步骤和调试过程}

4.1 熟悉控制台下常用命令

实验步骤
  • cmd命令进入控制台
  • dir 显示当前目录下所有内容。
  • 切换磁盘分区。
  • cd 进入某个目录。
  • 关于java的命令。

图 5个实验步骤图

4.2 JDK的配置与HelloWorld

实验步骤 {#b31393938323331393bb1eabcc7b0d9b7d6b1c8-实验步骤-1}
  • 学会设置环境变量JAVA_HOME、classpath与path(参考课件);
  • 学会使用java --version查看版本号,确认jre是否装好;
  • 学会使用记事本编写HelloWorld.java;
  • 使用命令行(cmd)行进行编译(javac)、运行(java)。

4.3 eclipse/intellij idea安装与使用

实验步骤 {#b31393938323331393bb1eabcc7b0d9b7d6b1c8-实验步骤-2}
  • 安装eclipse/intellij idea;
  • 新建一个Java Project;
  • 编写HelloWorld.java;
  • 运行HelloWorld,在eclipse或intellij idea控制台中查看结果。

4.4 筛法求素数

需求 {#b31393938323331383bb1eabcc7b0d9b7d6b1c8-需求}

编写一个程序,从键盘读取正整数n,使用筛法求不大于n的所有素数,并逐个打印出来。

实验步骤 {#b31393938323331393bb1eabcc7b0d9b7d6b1c8-实验步骤-3}

编写public static void printPrimeNumbers(int[]
n)方法,将不大于n的每个素数输出;

编写public static int[] getPrimeNumbers(int
n)方法,将不大于n的素数放入数组并返回。

编写main方法,输入n,调用getPrimeNumbers方法获取素数数组,再调用printPrimeNumbers方法输出这些素数。


测试数据设计 {#b31393938323332323bb1eabcc7b0d9b7d6b1c8-测试数据设计}
测试点1:1-10: 随机抽取10个
测试点2:1-100:随机抽取10个
测试点3:1-1000:随机抽取10个
测试点4:1-10000:随机抽取10个
测试点5:1-100000:随机抽取10个
测试点6:1-1000000:随机抽取10个
测试结果分析 {#b31393938323332353bb1eabcc7b0d9b7d6b1c8-测试结果分析}
n = 10
The prime numbers are: 2 3 5 7
n = 100
The prime numbers are: 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97
n = 500
The prime numbers are: 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97 101 103 107 109 113 127 131 137 139 149 151 157 163 167 173 179 181 191 193 197 199 211 223 227 229 233 239 241 251 257 263 269 271 277 281 283 293 307 311 313 317 331 337 347 349 353 359 367 373 379 383 389 397 401 409 419 421 431 433 439 443 449 457 461 463 467 479 487 491 499
n = 1000
The prime numbers are: 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97 101 103 107 109 113 127 131 137 139 149 151 157 163 167 173 179 181 191 193 197 199 211 223 227 229 233 239 241 251 257 263 269 271 277 281 283 293 307 311 313 317 331 337 347 349 353 359 367 373 379 383 389 397 401 409 419 421 431 433 439 443 449 457 461 463 467 479 487 491 499 503 509 521 523 541 547 557 563 569 571 577 587 593 599 601 607 613 617 619 631 641 643 647 653 659 661 673 677 683 691 701 709 719 727 733 739 743 751 757 761 769 773 787 797 809 811 821 823 827 829 839 853 857 859 863 877 881 883 887 907 911 919 929 937 941 947 953 967 971 977 983 991 997

部分测试结果如上,完整结果放在附件"测试结果1"中。

优化

前面使用的筛法问题在于筛法重复标记合数。例如12既会被2又会被3标记。根本原因在于没有唯一确定出产生数12的方式,因而使用欧式筛法。


4.5 最大公约数

需求 {#b31393938323331383bb1eabcc7b0d9b7d6b1c8-需求-1}

分别使用递归和非递归的算法,求解两个数的最大公约数。

实验步骤 {#b31393938323331393bb1eabcc7b0d9b7d6b1c8-实验步骤-4}

编写静态方法private static int gcd(int m, int n)用于实现非递归算法;


编写private static int gcd_recursive(int m, int n)用于实现递归算法;


编写主函数进行数据输入和最大公约数求解。


测试数据设计 {#b31393938323332323bb1eabcc7b0d9b7d6b1c8-测试数据设计-1}
测试点1:1-10: 随机抽取100对
测试点2:1-100:随机抽取100对
测试点3:1-1000:随机抽取100对
测试点4:1-10000:随机抽取100对
测试点5:1-100000:随机抽取100对
测试点6:1-1000000:随机抽取100对
测试结果分析 {#b31393938323332353bb1eabcc7b0d9b7d6b1c8-测试结果分析-1}
gcd(9106,8939) = 1
gcd(4282,8731) = 1
gcd(2855,2560) = 5
gcd(2930,7562) = 2
gcd(589,4826) = 19
gcd(568,6522) = 2
gcd(2900,5570) = 10
gcd(126071,775192) = 11
gcd(76305,196059) = 3
gcd(543019,351063) = 1
gcd(294942,128826) = 6
gcd(320856,50804) = 4

部分测试结果如上,完整结果放在附件"测试结果2"中。

4.6 求e的近似值

需求 {#b31393938323331383bb1eabcc7b0d9b7d6b1c8-需求-2}

使用计算机迭代法求e的近似值,且误差控制在10-6以内。

实验步骤 {#b31393938323331393bb1eabcc7b0d9b7d6b1c8-实验步骤-5}

编写静态方法public static double get_e() 用于求e的近似值。


编写main方法,用于输出e的近似值。


结果

e的近似值为:2.7182815

五、实验小结 {#五实验小结}

实验中遇到的问题及解决过程 {#实验中遇到的问题及解决过程}

没有什么问题。

实验中产生的错误及原因分析

错误:将测试结果输出到本地时发生错误"FileNotFoundException"。

原因分析:没有throws FileNotFoundException。

实验体会和收获。 {#实验体会和收获}

对java的语法掌握更加熟练了,和c差不多。 {#对java的语法掌握更加熟练了和c差不多}

六、附录 {#六附录}

打印HelloWorld

package test.pack;

public class HelloWorld {
	public static void main(String[] args) {
		System.out.println("HelloWorld");
	}
}

埃氏筛法求素数

package test.pack;

import java.util.Scanner;

public class Prime {

	public static void main(String[] args) {
		Scanner scanner = new Scanner(System.in);

		System.out.print("Please enter a positive integer:");
		int number = scanner.nextInt();
		System.out.printf("n = %d\n", number);

		int[] result = getPrimeNumbers(number);
		printPrimeNumbers(result);
	}

	public static void printPrimeNumbers(int[] result) {

		System.out.printf("The prime numbers are: ");
		for (int i = 0;; i++) {
			if (result[i] == 0)
				break;
			System.out.print(result[i] + " ");
		}
	}

	public static int[] getPrimeNumbers(int n) {
		int[] result = new int[n];
		int index = 0;
		int[] arr = new int[n + 1];
		for (int i = 2; i <= n; i++) {
			if (arr[i] == 0) {
				result[index++] = i;
			}
			for (int j = 2 * i; j <= n; j += i) {
				arr[j] = 1;
			}
		}
		return result;
	}
}

欧式筛法求素数

package test.pack;

import java.util.Scanner;

public class EulerPrime {
	public static void main(String[] args) {
		Scanner scanner = new Scanner(System.in);
		System.out.print("Please enter a positive integer:");
		int number = scanner.nextInt();
		System.out.printf("n = %d\n", number);
		int[] result = Euler_getPrimeNumbers(number);
		printPrimeNumbers(result);
		System.out.println();
	}

	public static void printPrimeNumbers(int[] result) {

		System.out.printf("The prime numbers are: ");
		for (int i = 0;; i++) {
			if (result[i] == 0)
				break;
			System.out.printf("%d ", result[i]);
		}
	}

	public static int[] Euler_getPrimeNumbers(int n) {
		int[] result = new int[n], arr = new int[n + 1];
		int index = 0;
		arr[0] = arr[1] = 1;
		for (int i = 2; i <= n; i++) {
			if (arr[i] == 0)
				result[index++] = i;
			for (int j = 0; j < index && i * result[j] <= n; j++) {
				arr[i * result[j]] = 1;
				if (i % result[j] == 0) {
					break;
				}
			}
		}
		return result;
	}
}

求最大公因数

package test.pack;

import java.util.Scanner;

public class GCD {
	public static void main(String[] args) {
		Scanner scanner = new Scanner(System.in);

		System.out.print("Please enter two positive integers:");
		int m = scanner.nextInt(), n = scanner.nextInt();
		int result = gcd(m, n);
		System.out.printf("%d和%d最大公因数为%d\n", m, n, result);
	}

	private static int gcd(int m, int n) {
		if (m < n) {
			int t = m;
			m = n;
			n = t;
		}
		while (m % n != 0) {
			int yu = m % n;
			m = n;
			n = yu;
		}
		return n;
	}

	private static int gcd_recursive(int m, int n) {
		if (m < n) {
			int t = m;
			m = n;
			n = t;
		}
		if (m % n == 0)
			return n;
		return gcd_recursive(n, m % n);
	}
}

求e的近似数

package test.pack;

public class e {
	public static void main(String[] args) {
		double e = get_e();
		System.out.printf("e的近似值为:%.7f", e);
	}

	public static double get_e() {
		double threshold = 1e-6;
		double demo = 1, cnt = 1;
		double e = 1;
		while (1 / demo > threshold) {
			e += 1 / demo;
			demo *= ++cnt;
		}
		return e;
	}
}