实验内容

  1. 用while循环语句,计算1-200之间的所有3的倍数之和。
  2. 用switch语句实现判断某年的某个月份有几天的程序。
  3. 水仙花数是指其个位、十位、和百位上三个数的立方之和等于这个数本身。通过循环,判断100-999之间所有的数字,符合水仙花数条件的数字。
  4. 已知XYZ+YZZ = 532,其中X、Y和Z为数字,编程求出X、Y和Z的值。
  5. 编程实现“百钱买百鸡”问题。母鸡5钱一只,公鸡3钱一只,小鸡1钱三只,现在有百钱欲买百鸡,有多少种卖买法?程序分别用三种方法来写:① 第一方法是程序中有三层的循环,这个效率最低;② 第二方法是程序采用两层循环实现;③ 第三方法是程序采用一层循环实现。
  6. 一个整数的各位数字之和能被9整除,则该数也能被9整除。验证这个定理的正确性。注:验证从0–2147483647的整数中是否存在不符合该定理的数,若不存在即验证通过,验证时间可能需要2-4分钟,请耐心等待,但如果时间太长,务必思考为什么…
  7. 有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问2年后的兔子总数为多少?(尝试用递归编程实现)

Exam1

  1. 用while循环语句,计算1-200之间的所有3的倍数之和。

流程图

img

code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package project3;

public class Exam1 {
public static void main(String[] args) {
int i = 1;
int n = i*3;
int sum = 0;
while (n<=200){
sum +=n;
i++;
n = i*3;
}
System.out.println("1-200之间的所有3的倍数之和为 "+sum);
}
}

运行结果

img

Exam2

  1. 用switch语句实现判断某年的某个月份有几天的程序。

流程图

img

code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
package project3;

import java.time.Year;
import java.util.Scanner;

public class Exam2 {
public static void main(String[] args) {
int year = 0;
int month = 0;
int day;
Scanner s1 = new Scanner(System.in);
Scanner s2 = new Scanner(System.in);

while (true){
System.out.println("请输入年份:");
if(s1.hasNextInt()) {
year = s1.nextInt();
} else break;
System.out.println("请输入月份:");
if(s2.hasNextInt()) {
month = s2.nextInt();
}
day = new Exam2().Day(year,month);
System.out.println(year+"年"+month+"月一共有"+ day+"天\n");
}
}
public int Day(int year,int month){
int i = 0;
if((year%400)==0((year%4==0)&&(year%100!=0))){
i++;
}
switch (month)
{
case 1:
return 31;
case 2:
return 28+i;
case 3:
return 31;
case 4:
return 30;
case 5:
return 31;
case 6:
return 30;
case 7:
return 31;
case 8:
return 31;
case 9:
return 30;
case 10:
return 31;
case 11:
return 30;
case 12:
return 31;
default:
return 0;
}
}
}

运行结果:

img

本程序采用while提供多次输入查询年月天数,当输入整型以外的数据,则结束循环。

Exam3

  1. 水仙花数是指其个位、十位、和百位上三个数的立方之和等于这个数本身。通过循环,判断100-999之间所有的数字,符合水仙花数条件的数字。

流程图

img

code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package project3;

public class Exam3 {
public static void main(String[] args) {
//记录水仙花数的总和
int sum = 0;
//存放数字的个位
int digits;
//存放数字的十位
int tens;
//存放数字的百位
int hundreds;
System.out.println("100-999的水仙花数有:");
for(int i = 100;i <= 999;i++){
hundreds = i/100;
tens = (i-hundreds*100)/10;
digits = i-hundreds*100-tens*10;
if(i==(int)(Math.pow(digits,3)+Math.pow(tens,3)+Math.pow(hundreds,3))){
sum++;
System.out.println(i+"\t");
if(sum%5==0){
System.out.println();
}
}
}
System.out.println("100-999的水仙花数共有"+sum+"个");
}
}

运行结果

img

Exam4

  1. 已知XYZ+YZZ = 532,其中X、Y和Z为数字,编程求出X、Y和Z的值。

流程图

img

code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
package project3;

public class Exam4 {
public static void main(String[] args) {

for (int x = 0; x < 6; x++)
for (int y = 0; y < 6; y++)
for (int z = 0; z < 10; z++) {
if ((x * 100 + y * 10 + z + y * 100 + z * 10 + z) == 532) {
System.out.println("XYZ+YZZ = 532");
System.out.println("其中X的值为" + x + ",Y的值为" + y + ",Z的值为" + z + "。");
}
}

for (int y = 0; y < 6; y++)
for (int x = 0; x < 6; x++)
for (int z = 0; z < 10; z++) {
if ((x * 100 + y * 10 + z + y * 100 + z * 10 + z) == 532) {
System.out.println("XYZ+YZZ = 532");
System.out.println("其中X的值为" + x + ",Y的值为" + y + ",Z的值为" + z + "。");
}
}

for (int z = 0; z < 10; z++)
for (int x = 0; x < 6; x++)
for (int y = 0; y < 6; y++) {
if ((x * 100 + y * 10 + z + y * 100 + z * 10 + z) == 532) {
System.out.println("XYZ+YZZ = 532");
System.out.println("其中X的值为" + x + ",Y的值为" + y + ",Z的值为" + z + "。");
}
}
}
}

运行结果

img

程序调整了变量在for循环的嵌套顺序,三种输出结果均相同。从运行结果相同可知,并没有漏解。

Exam5

  1. 编程实现“百钱买百鸡”问题。母鸡5钱一只,公鸡3钱一只,小鸡1钱三只,现在有百钱欲买百鸡,有多少种卖买法?程序分别用三种方法来写:

① 第一方法是程序中有三层的循环,这个效率最低;

② 第二方法是程序采用两层循环实现;

③ 第三方法是程序采用一层循环实现。

流程图

img

code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
package project3;

public class Exam5 {
public static void main(String[] args) {

long startTime1 = System.nanoTime();
struct1();
long endTime1 = System.nanoTime();
float runTime1 = (float)(endTime1-startTime1)/1000;
System.out.println("3层循环运行时间:"+runTime1+"μs");
System.out.println();

long startTime2 = System.nanoTime();
struct2();
long endTime2 = System.nanoTime();
float runTime2 = (float)(endTime2-startTime2)/1000;
System.out.println("2层循环运行时间:"+runTime2+"μs");
System.out.println();

long startTime3 = System.nanoTime();
struct3();
long endTime3 = System.nanoTime();
float runTime3 = (float)(endTime3-startTime3)/1000;
System.out.println("1层循环运行时间:"+runTime3+"μs");


}

public static void struct1()
{
int i = 0;
//设x为购买公鸡数,y为购买母鸡数,z为购买小鸡数
for(int x = 0;x <= 100/5;x++)
for(int y = 0;y <= 100/3;y++)
for(int z = 0;z <= 100;z++){
if(((x*5+y*3+z/3)==100)&&((x+y+z)==100)&&(z%3==0)){
i++;
System.out.println("第"+i+"种卖法:"+x+"只公鸡,"+y+"只母鸡,"+z+"只小鸡");
}
}
}

public static void struct2(){
int i = 0;
//设x为购买公鸡数,y为购买母鸡数,z为购买小鸡数
for(int x = 0;x <= 100/5;x++)
for(int y = 0;y <= 100/3;y++){
int z = 100 - x - y;
if(((x*5+y*3+z/3)==100)&&(z%3==0)){
i++;
System.out.println("第"+i+"种卖法:"+x+"只公鸡,"+y+"只母鸡,"+z+"只小鸡");
}
}
}

public static void struct3(){
int i = 0;
for(int x = 0;x <= 100/5;x++){
int y = 25 - 7*x/4;
int z = 75 + 3*x/4;
if((x+y+z==100)&&((x*5+y*3+z/3)==100)&&(y>=0)&&(z%3==0)){
i++;
System.out.println("第"+i+"种卖法:"+x+"只公鸡,"+y+"只母鸡,"+z+"只小鸡");
}
}
}

}

运行结果

img

程序运行了三种嵌套方法运行并采用时间监测获取不同嵌套方法的执行时间。由结果可知,3层嵌套for循环毫无疑问执行时间最长,效率最低。2层循环和1层循环执行效率相差不大。

Exam6

  1. 一个整数的各位数字之和能被9整除,则该数也能被9整除。验证这个定理的正确性。

注:验证从0–2147483647的整数中是否存在不符合该定理的数,若不存在即验证通过,验证时间可能需要2-4分钟,请耐心等待,但如果时间太长,务必思考为什么…

流程图

img

code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package project3;

public class Exam6 {
public static void main(String[] args) {
long startTime = System.currentTimeMillis();

for (int i = 0;i<2147483647;i++){

if(i%9==0) continue;
int num = i;
int sum = 0;
while (num != 0) {
sum+=num%10;
num=num/10;
}
if(sum%9==0)
System.out.println(i);
}
long endTime = System.currentTimeMillis();
System.out.println("RunTime = "+(endTime - startTime)/1000+"s");
}
}

运行结果

img

无不满足定理的特例,验证通过,运行时间39s。

起初是想先计算遍历的数的位数,从最高位到最低位依次存入数组,再相加,但是需要每一次for循环都要调用依次检测位数的方法,相当于要调用2^31次其他方法,这样增加了算力,程序确实运行时间很长。最后改为从最低位开始存入数组,虽然每一次for循环都要存10位数,但是比起调用一次方法,还是要快很多。

Exam7

  1. 有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问2年后的兔子总数为多少?(尝试用递归编程实现)

其实这就是一个斐波那契数列*2的程序……

流程图

img

code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package project3;

public class Exam7 {
public static void main(String[] args) {
int i = 1;
int k;
int num = 0;
long startTime = System.nanoTime();
for(int month = 0;month < 36;month++){
k = num;
num += i;
i = k;
}
long endTime = System.nanoTime();
System.out.println("2年后的兔子总数为"+num*2+"只");
System.out.println("RunTime = "+(endTime-startTime)+"ns");
}
}

利用递归:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package project3;

public class Exam7_1 {
public static void main(String[] args) {
int num;
long startTime = System.nanoTime();
num = Fibo(36)*2;
long endTime = System.nanoTime();
System.out.println("2年后的兔子总数为"+num+"只");
System.out.println("RunTime = "+(endTime-startTime)+"ns");
}

public static int Fibo(int month){
if((month == 1)(month == 2)) return 1;
else if(month>2) return Fibo(month-1)+Fibo(month-2);
else return 0;
}
}

运行结果

img

递归运行结果:

img

比较不使用递归和使用递归的程序可知,调用函数会浪费大量的算力,递归则需要大量的调用函数,因此在能不使用递归的情况下尽量不使用。

实验心得

在编写程序考虑算法时,应尽量地避免递归和多层嵌套。