Java程序设计实验2 | Java语言基础(二)

简介: 分别用do-while和for循环计算1+1/2!-1/3!+1/4!-1/5!…的前20项之和。

Java程序设计实验2 | Java语言基础(一)+https://developer.aliyun.com/article/new?spm=a2c6h.13148508.J_eBhO-wcawiLJRkGqHmozR.89.23164f0egQsi1H#/


3、实验题目:循环结构的应用


1)分别用do-while和for循环计算1+1/2!-1/3!+1/4!-1/5!…的前20项之和。

本题是基础的累加、阶乘的运用。较为基础,故不多作说明。


源代码:


for循环实现


public class S2_3_1 {
    public static void main(String[] args) {
        double sum = 0;
        double fact = 1;
        for(int i = 1; i <= 20; i++){
            fact *= i;    //求每项中的阶乘
            sum += 1/fact;    //将各项累加
        }
        System.out.println(sum);
    }
}


do-while循环实现


public class S2_3_1 {
    public static void main(String[] args) {
        double sum = 0;
        double fact = 1;
        int i = 1;
        do {
            fact *= i++;
            sum += 1/fact;
        }while(i <= 20);
 
        System.out.println(sum);
    }
}


列出测试数据和实验结果截图:



(2)求1000以内的完全数(一个数等于它的因子之和称为完全数)


通过试除法,找到数n所有的因子并相加,最后作判断即可。


源代码:


public class S2_3_2 {
    //判断是否是完全数的方法
    public static boolean isPerfectNumber(int n){
        //一个数等于它的因子之和称为完全数
        int sum = 0;    //用于记录因子之和
        for(int i = 1; i <= n/2; i++){    //试除法寻找因子
            if(n%i == 0){    
                sum += i;    //此处i即n的因子
            }
        }
        //比较因子之和与这个数本身是否相等
        if(sum == n){
            return true;
        }else{
            return false;
        }
    }
 
    public static void main(String[] args) {
        for(int n = 6; n <= 1000; n++){
            if(isPerfectNumber(n)){
                System.out.println(n);
            }
        }
    }
}




(3)微信中的一个拿鸡蛋问题


一筐鸡蛋,1个1个拿,正好拿完。


    2个2个拿,还剩1个。


    3个3个拿,正好拿完。


    4个4个拿,还剩1个。


    5个5个拿,还差1个。


    6个6个拿,还剩3个。


    7个7个拿,正好拿完。


    8个8个拿,还剩1个。


    9个9个拿,正好拿完。


问:筐里最少有多少鸡蛋?


这个问题非常简单,但必须注意细节:5个5个拿时,是还“差”一个,而不是还“剩”一个。假设有4个鸡蛋,那么此时5个5个拿,就是还差一个的情景。因此,此时的鸡蛋数加上差的1个,恰好是5的倍数。


源代码:


public class S2_3_3 {
    public static void main(String[] args) {
        int i = 0;
        while(true) {
            i++;
            if(i%2==1 && i%3==0 && i%4==1 && (i+1)%5==0 && i%6==3 && i%7==0 && i%8==1 && i%9==0){
                System.out.println(i);
                break;
            }
        }
    }
}


列出测试数据和实验结果截图:



5、实验题目:课后作业题


(1)求六边形面积,六边形面积可以通过下面公式计算(s是边长)



注:使用Math类中的方法计算tan值。


源代码: 


public class Test {
    public static void main(String[] args) {
        Scanner reader = new Scanner(System.in);
        double s = reader.nextDouble();
        System.out.println(getArea(s));
    }
    public static double getArea(double s){
        double x1 = 6*Math.pow(s,2);
        double x2 = 4*Math.tan(Math.PI/6);
        return x1/x2;
    }
}


列出测试数据和实验结果截图: 



(2)实现会员注册,要求用户名长度不小于3,密码长度不小于6,若不满足需有提示信息,提示输入有误;注册时两次输入密码必须相同(字符串)


本题的关键是字符串的输入与两个字符串之间的比较方法equals的运用。注意,若要求忽略大小写比较,则用到equalsIgnoreCase()方法。


源代码:


import java.util.Scanner;
public class S2_5_2 {
    public static void main(String[] args) {
        Scanner reader = new Scanner(System.in);
        System.out.println("请输入用户名:");
        String userName = reader.next();
        while(userName.length() < 3) {
            System.out.println("用户名长度不可小于3!请重新输入:");
            userName = reader.next();
        }
        System.out.println("请输入密码:");
        String password = reader.next();
        while(password.length() < 6) {
            System.out.println("密码长度不可小于6!请重新输入:");
            password = reader.next();
        }
        System.out.println("请确认密码:");
        String confirmPassword = reader.next();
        if(confirmPassword.equals(password)) {
            System.out.println("注册成功!");
        }else {
            System.out.println("两次密码不一致!");
        }
    }
}


列出测试数据和实验结果截图:




(3)找出两个分教最高的学生:编写程序,提示输入学生的个数、每个学生的名字及其分数,最后显示获得最高分的学生和第二高分的学生


方法一:直接求解


该代码没有用到面向对象的思想,编程思路是分别创建两个数组:分数数组与姓名数组进行分开存储。通过排序代码,以分数为标准对姓名数组进行排序,最后输出前两项的姓名。


源代码:


import  java.util.Scanner;
 
public class S2_5_3 {
    public static void main(String[] args) {
        Scanner reader=new Scanner(System.in);
 
        System.out.println("请输入学生个数");
        int num = reader.nextInt();
 
        //创建分数数组和姓名数组进行分开存储
        int[] score = new int[num];
        String[] name = new String[num];
 
        for(int i=0;i<num;i++)
        {
            System.out.println("请输入第"+(i+1)+"个学生的名字");
            name[i]= reader.next();
            System.out.println("请输入第"+(i+1)+"个学生的成绩");
            score[i]=reader.nextInt();
        }
 
        //直接选择排序
        for(int i=0;i<num;i++)
        {
            for(int j=i+1;j<num;j++)
            {
                if(score[i]<score[j])
                {
                    String tmp = name[i];
                    name[i] = name[j];
                    name[j] = tmp;
                }
            }
        }
 
        System.out.println("第一名为:"+name[0]+"。第二名为:"+name[1]);
    }
}


列出测试数据和实验结果截图:



方法二:面向对象


该方法是上一种方式的优化,核心思路是实现Student类,创建Student数组,并通过直接对Student数组排序的方式最高分的Student对象与第二高分的Student对象。


注意:由于数组排序的过程中设计对象的比较,因此需要重写compareTo()方法才能进行Student数组的排序。


 源代码: 


import java.util.Arrays;
import java.util.Scanner;
 
public class S2_5_3 {
    public static void main(String[] args) {
        Scanner reader = new Scanner(System.in);
        System.out.println("请输入学生的个数:");
        int num = reader.nextInt();
        Student[] students = new Student[num];
        System.out.println("请依次输入学生的姓名与分数:");
        for (int i = 0; i < students.length; i++){
            System.out.println("学生"+(i+1));
 
            String namei = reader.next();   //① 注意:写成.next()和.nextLine()在此有区别!
            int scorei = reader.nextInt();    //②
            students[i] = new Student(namei,scorei);    //③
        }
        Arrays.sort(students);    //④
 
        System.out.println("获得最高分的学生是:" + students[0]);
        System.out.println("获得第二高分的学生是:" + students[1]);
    }
}
 
class Student implements Comparable<Student>{    //⑤
    String name;
    int score;
 
    public Student(String name, int score) {
        this.name = name;
        this.score = score;
    }
 
    //重写compareTo方法以数组排序
    @Override
    public int compareTo(Student o) {
        return o.score-this.score;
    }
 
    //重写toString方法以打印对象
    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", score=" + score +
                '}';
    }
}

 

代码详解:                


  1. 注释①处写成.next()和.nextLine()在此是有区别的。正确的方式应当是写成reader.next(); 一方面,.next()不会因为获取到上一个输入遗留下来的换行空白符而停止读取;另一方面,在用户实际输入的时候既可以将“姓名”和“分数”用换行隔开,也可以用空格等非换行符隔开。若写成.nextLine()。则会有上面的两个问题,会抛出InputMismatchException




  1. ③处代码是创建新的Student对象。注意,在创建Student数组的时候,并没有实例化Student对象。数组没有初始化,因此Student数组内均为null。通过构造方法给Student对象的name和score赋值,并实例化数组中的元素。
  2. ④直接调用Arrays中的方法sort给数组中的元素进行排序。注意:该数组是引用类型,要实现排序必须重写Comparable或Comparator接口,并重写相应的比较方法,也就是指定比较的规则。
  3. ⑤处实现了Comparable接口。


列出测试数据和实验结果截图:



(4)定义一维数组并初始化,通过键盘任意输入一个数,查找该数是否存在(结果返回下标值)


方法一:数组中查找比对


源代码:


import java.util.Arrays;
import java.util.Scanner;
 
public class S2_5_44 {
    public static void main(String[] args) {
        Scanner reader=new Scanner(System.in);
        int[] array={0,1,2,3,4,5,6,7,8,9};
        System.out.println("数组为:");
        System.out.println(Arrays.toString(array));
 
        System.out.println("请输入一个数:");
        int num = reader.nextInt();
 
        int i = 0;
        for(; i < array.length; i++)
        {
            if(num == array[i])
            {
                break;
            }
        }
        if(i < array.length){
            System.out.println("该数存在,下标为" + i);
        }else{
            System.out.println("没有找到");
        }
    }
}


列出测试数据和实验结果截图: 





方法二:将数组转变为字符串后,调用indexOf()方法


注意,将int数组转换为String,不能直接调用Arrays.toString()方法。因为该方法输出的内容并不完全是原数组中的,而是还有分隔符逗号、前后中括号[] 等。通过调试可以看到:



我们希望0下标的位置是"0",但这里却是"["。Java中没有库函数可以实现int数组直接转换成String的方法,因此我们需要自己实现一个myToString()来完成,逻辑也并不难。


源代码:


import java.util.Arrays;
import java.util.Scanner;
 
public class S2_5_4 {
    public static void main(String[] args) {
        Scanner reader = new Scanner(System.in);
        int[] array = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
        System.out.println("数组为:");
        System.out.println(Arrays.toString(array));
 
        System.out.println("请输入一个数:");
        int num = reader.nextInt();
        //将待查找的数转变成String类型,再查找
        String strNum = String.valueOf(num);
        //调用自己实现的方法,将int数组转变成String数组
        String strArray = myToString(array);
        
        //获取查找下标值
        int ret = strArray.indexOf(strNum);
        if(ret != -1){
            System.out.println("找到了,下标是:" + ret);
        } else {
            System.out.println("没有找到");
        }
    }
 
    //自己实现将int数组转换为String的方法
    public static String myToString(int[] array) {
        String str = "";
        for (int x : array) {
            str += x+"";
        }
        return str;
    }
}


列出测试数据和实验结果截图:





方法三:调用Arrays工具类中的binarySearch()方法


如图,这是binarySearch()一个方法的api文档。通过文档可知,配合sort()方法,可以直接调用二分查找方法实现查找。



源代码:


import java.util.Arrays;
import java.util.Scanner;
 
public class S2_5_4 {
    public static void main(String[] args) {
        Scanner reader = new Scanner(System.in);
        int[] array = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
        System.out.println("数组为:");
        System.out.println(Arrays.toString(array));
 
        System.out.println("请输入一个数:");
        int num = reader.nextInt();
        Arrays.sort(array);    //必须先进行排序
        int ret = Arrays.binarySearch(array,num);    //调用二分查找方法
 
        if(ret < 0) {
            System.out.println("没有找到!");
        }else{
            System.out.println("找到了,下标为" + ret);
        }
    }
}

(5)编写一个程序,将二维数组a转置后存入数组b(所谓转置就是行列互换)

例如:


源代码:


import java.util.Arrays;
import java.util.Scanner;
public class S2_5_5 {
    public static void main(String[] args) {
        Scanner reader = new Scanner(System.in);
 
        System.out.println("请输入数组的行数n与列数m:");
        int n = reader.nextInt();
        int m = reader.nextInt();
        int[][] src = new int[n][m];
        int[][] dst = new int[m][n];
 
        System.out.printf("请输入一个%d*%d的数组:\n",n,m);
        for(int i = 0; i < src.length;i++)
        {
            for(int j = 0; j < src[i].length; j++)
            {
                src[i][j] = reader.nextInt();
            }
        }
 
        for(int i = 0; i < dst.length; i++)
        {
            for(int j = 0; j < dst[i].length; j++)
            {
                dst[i][j] = src[j][i];
            }
        }
 
        System.out.println("转制后的二位数组为:");
        //System.out.println(Arrays.deepToString(dst));
        for(int i = 0; i < dst.length; i++)
        {
            for(int j = 0; j < dst[i].length; j++)
            {
                System.out.print(dst[i][j] + " ");
            }
            System.out.println();
        }
    }
}

列出测试数据和实验结果截图:


实验总结


  1. 完成上述实验,我更熟地掌握了Java的基础语法,包括:

          1.  Java关于标识符的命名规则,Java标识符可以字母、数字、下划线和美元符构成,且数字不能开头。类名用大驼峰,变量名、方法名用小驼峰。

          2.  掌握了8种基本数据类型int,byte,short,char,long,float,double,Boolean的使用情况和相应的类型转换方法。

          3.   我熟悉了各种运算符包括自增、自减、三目运算符等的优先级和结合方向。

          4.   我掌握了控制结构的3种语句,包括if、switch选择语句、while、do-while、for、for-each循环语句。

          5.   我掌握了Java输入数据的基本方法:Scanner。我可以熟练地通过调用Scanner对象输入各种数据类型的数据进行编程。


          6.   我掌握了方法的定义和调用格式,能正确写出Java定义方法的语法。也理解了方法调用和参数传递的原理,包括值传递和址传递。

         7.    我掌握了方法的重载,重载的条件是方法的名称必须相同,参数列表必须不同,返回值类型不做要求。

         8.    我也理解了方法的递归调用,递归就是方法自己调用自己,会在虚拟机栈中建立栈帧。

         9.    在与数组相关的实验中,我掌握了数组的定义、动态和静态初始化格式。我能通过for循环对一维数组和二维数组进行遍历,能完成数组的转置、数组的排序,构建引用类型的数组。也可以熟练通过Array工具类,直接调用Arrays中的方法进行数组排序和逆序。


  1. 在编程中我没有遇到难以解决的问题。遇到唯一的问题是在求完数时,本来需要对一个数进行试除,然后计算该数的所有因子之和。我在for循环判断试除因子范围时,将i的界限写成了i <=Math.sqrt(n),但输出结果有误(什么也没输出)。通过调试,后来我将i 改为 i <= n/2,就能正确输出结果了。这是因为我一开始没有意识到因子有对称性这个特点。
  2. 最后,通过实验,我对基础算法进行了很好的复习。


相关文章
|
7天前
|
数据可视化 Java
Java语言使用DL4J实现图片分类
【6月更文挑战第14天】Java语言使用DL4J实现图片分类
18 3
|
3天前
|
Java 数据安全/隐私保护 开发者
Java是一种完全支持面向对象编程的语言,其面向对象特性包括封装、继承、多态和抽象等
【6月更文挑战第18天】**面向对象编程(OOP)通过对象封装状态和行为,实现问题域的抽象。Java全面支持OOP,核心特性包括**: - **封装**:保护数据安全,隐藏内部细节。 - **继承**:子类继承父类属性和行为,促进代码重用。 - **多态**:一个接口多种实现,增强灵活性和扩展性。 - **抽象**:通过接口和抽象类抽离共性,简化复杂性。 **Java的OOP便于理解和解决复杂系统问题。**
14 3
|
6天前
|
存储 小程序 前端开发
java毕设项目|宿舍管理系统小程序设计与实现
java毕设项目|宿舍管理系统小程序设计与实现
|
6天前
|
监控 Java API
Java 程序设计 第八章 线程
Java 程序设计 第八章 线程
|
2天前
|
Java 大数据 API
|
6天前
|
IDE Oracle Java
[笔记] 疯狂JAVA讲义(第3版) 第1章 Java语言概述与开发环境
[笔记] 疯狂JAVA讲义(第3版) 第1章 Java语言概述与开发环境
|
7天前
|
Java
Java 程序设计 第七章 文件管理与输入/输出 笔记
Java 程序设计 第七章 文件管理与输入/输出 笔记
|
7天前
|
Java Android开发
Java 程序设计 第6章 异常与断言 笔记
Java 程序设计 第6章 异常与断言 笔记
|
1天前
|
Java
死锁是线程间争夺资源造成的无限等待现象,Java示例展示了两个线程各自持有资源并等待对方释放,导致死锁。`
【6月更文挑战第20天】死锁是线程间争夺资源造成的无限等待现象,Java示例展示了两个线程各自持有资源并等待对方释放,导致死锁。`volatile`保证变量的可见性和部分原子性,确保多线程环境中值的即时更新。与`synchronized`相比,`volatile`作用于单个变量,不保证原子操作,同步范围有限,但开销较小。`synchronized`提供更全面的内存语义,保证原子性和可见性,适用于复杂并发控制。
11 3
|
1天前
|
Java 开发者
JAVA多线程初学者必看:为何选择继承Thread还是Runnable,这其中有何玄机?
【6月更文挑战第19天】在Java中创建线程,可选择继承Thread类或实现Runnable接口。继承Thread直接运行,但限制了多重继承;实现Runnable更灵活,允许多线程共享资源且利于代码组织。推荐实现Runnable接口,以保持类的继承灵活性和更好的资源管理。