ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

java总结性Blog-2

2022-05-08 14:01:36  阅读:171  来源: 互联网

标签:总结性 java abs double 代码 Blog points Math String


一、前言:

【PTA第四次题目集、超星作业以及期中考试】

知识点:主要涉及到了类的设计;面向对象程序设计的三大特性:封装、继承、多态;正则表达式;泛型等等。

题量:PTA第四次题目集只有三题,题量不大,但是第二题的题目很长,写PTA的绝大部分时间都花在了第二题上;慕课作业和期中考试的题量均较小。

难度:PTA作业的第二题较难,要用到很多的计算几何的知识,其余题目都比较基础;慕课作业和期中考试的题目均比较基础,主要考察我们的java基础有没有打牢,基础教好的同学写起来还是没有难度的。

--------------------------------------------------------------------------------------------------------------------------------------------------------

二、设计与分析:

【PTA第四次题目】

第一题:

这一题主要是考察我们正则表达式的使用,要在一段文字中提取出数字。

关于如何提取数字,我刚开始的思路是按照汉字和标点符号以及空格等等把字符串分开,但是这样就会随之产生三个问题:

1.怎么去掉汉字?2.怎么去掉标点符号?3.怎么去掉空格?

在网上查阅正则表达式之后,我找到了一个可以去掉双字节的正则表达式,我们知道,汉字和绝大部分的中文标点是双字节的,但仍有部分标点是单字节的,所以行不通。

那么这时我换了一种思路,即“正难则反”:

去掉不是数字的字符,剩下的就是我们想要的数字了,这个正则表达式也很简单:

[^\\d+],也可以写成"\\D+",二者是等价的,都指的是:按非数字的字符为分隔符

核心代码:

String[] split = dataLine.split("[^\\d+]");
            int sum = 0;
            for(int i = 0;i < split.length;i++){
                if(!split[i].equals(""))
                {
                    int digit=Integer.parseInt(split[i]);
                    sum+=digit;
                }
            }

 

踩坑心得:

1、编译报错“ 解析时已到达文件结尾”

原因:大括号未对齐,少了一半

此类错误通常是括号没对齐。

 

2.运行时报错“NumberFormatException”

java.lang.NumberFormatException指数字格式异常。当试图将一个String转换为指定的数字类型,而该字符串确不满足数字类型要求的格式时,抛出该异常

原因:将String转换成int型时,String中有中文符号。

 

3、分组之后的字符串中出现空格

spilt是正则表达式中的一种,用来切分字段,如果切分的字段连续出现,就会生成空值。

因此,我们在将String转换成int时,要加上判断语句“if(!split[i].equals(""))”

 

4.运行时异常:IndexOutOfBoundsException

数组角标越界

原因:对ArrayList<>()还未有元素时使用set()方法

应把set()改成add()进行元素的添加

 

5.控制读取字符串的相关错误:

正则表达式正确当结果仍然是“Wrong Format”

原因:input.next(),只读了一个字符串,应该将代码改为是input.nextLine();

---------------------------------------------------------------------------------------------------------------------

 

第二题:

本题延续了前几次的PTA题目风格,仍然是与计算几何密切相关的题目,不过从三角形升级到了四边形,很多在三角形题目的代码也可以在本题中使用。

写这题的时候,我们应该把点类,线类,三角形类都先准备好,这些类的又可以为四边形类服务,面向对象编程的知识点考察的不多,主要是数学计算。

根据题意,我们首先进行基本格式校验,这里仍然用到的是正则表达式:

if(!data.matches("[1-4]:[+-]?\\d+,[+-]?\\d+(\\s[+-]?\\d+,[+-]?\\d+)*")){
            System.out.println("Wrong Format");
        }

这个正则表达式虽然看起来长,但它是由很多简单的正则组成的,[+-]? 表示的是是否出现+、-,如果有,只能出现一次,\\d+表示至少出现一次数字,\\s想必大家都不陌生,表示对空格、tab等等的校验,最后的“*”指出现0次或多次。

 

 

其次,我们根据用户输入的choice判断执行哪段代码

①:choice ==1:

首先对坐标个数进行校验:

if(xy.length != 9){
                        System.out.println("wrong number of points");
                    }

(在本题中我并没有定义自定义的Point类,这导致我之后的写起来代码比较麻烦,当然也可以不用自定义,API中有Point2D.Double类也是一个点类)

-------------------------------------------------------------------------------------------------------------------------------------------------------------

 

其次,调用在自定义类中“class CalculationOfQuadrilaterals”的方法:

if(!calculation.isFourCoincide(point)){
                            boolean isQuad = calculation.isQuadrilateral(point);
                            boolean[] judge = calculation.judgeQuadrilateral(point);
                            System.out.println(judge[0] + " " + judge[1]);
                        }else{
                            System.out.println("points coincide");
                        }

 

---------------------------------------------------------------------------------------------------------------------------------------------------------------

这里的isFourCoincide()方法用来判断四个点是否重合:

public boolean isFourCoincide(Integer[] points){
        return isTwoCoincide(points[0], points[1], points[2], points[3]) || isTwoCoincide(points[0], points[1], points[4], points[5])
                || isTwoCoincide(points[0], points[1], points[6], points[7]) || isTwoCoincide(points[2], points[3], points[4], points[5])
                || isTwoCoincide(points[2], points[3], points[6], points[7]) || isTwoCoincide(points[4], points[5], points[6], points[7]);
    }

 

isQuadrilateral(Integer[] points)方法判断是否为四边形:

我使用的算法是:使用向量积,如果两个两条边共线的话是构不成四边形的,此时他们的向量积为0,使用此方法要注意向量的方向,不要弄反了。

public boolean isQuadrilateral(Integer[] points){//判断是否为四边形
        double xAB, yAB, xBC, yBC, xCD, yCD, xDA, yDA;
        xAB = points[2] - points[0];
        yAB = points[3] - points[1];
        xBC = points[4] - points[2];
        yBC = points[5] - points[3];
        xCD = points[6] - points[4];
        yCD = points[7] - points[5];
        xDA = points[6] - points[0];
        yDA = points[7] - points[1];
        return  Math.abs(xAB * yBC - xBC * yAB) > 0.001 && Math.abs(xBC * yCD - xCD * yBC) > 0.001 && Math.abs(xCD * yDA - xDA * yCD) > 0.001
                && Math.abs(xAB * yDA - xDA * yAB) > 0.001;
    }

---------------------------------------------------------------------------------------------------------------------------------------------------

 

 

踩坑心得:

关于浮点数的比较,我们应尽量少的使用“==”和“!=”,因为浮点数在实际储存中是由精度缺失的。

因此,为了得到我们想要的结果,应用“>=”或者"<="比较:

例如:1)比较一个浮点数是否为0:a <= 0.001;一般来说我们用0.001就可以了,如果是十分精细的计算,我们也可以用科学计数法,aE-6

   2)判断两个浮点数是否相等:abs( fa - fb) < 0.001,要加上绝对值

-------------------------------------------------------------------------------------------------------------------------------------------------------------

 

 

接着,如果是四边形,我们继续使用“judgeQuadrilateral(Integer[] points)”方法判断四边形的类型:

我的思路:

①.判断是否为凸四边形:计算内角和是否为2PI

这个算法比较简单,只需要把四边形分成两个三角形,分别用余弦定理求出角度即可。注意,这里的角度都是以弧度制为单位的。

 

②.判断是否为平行四边形:

在①的基础上,我们只需要判断两组对边是否分别相等即可

 

③.判断是否为菱形:

在②的基础上,只用判断一组邻边是否相等即可,都很简单。

 

④.判断是否为矩形:

在②的基础上,只用判断一个角是否是直角即可。

 

⑤.判断是否为正方形:

在④的基础上,只需判断邻边是否相等即可。

在写这些代码前,我们要先把边和角都计算好。

 核心代码:

public boolean[] judgeQuadrilateral(Integer[] points){
        boolean[] judge = new boolean[5];
        double AB = Math.sqrt((points[0] - points[2]) * (points[0] - points[2]) + (points[1] - points[3]) * (points[1] - points[3]));
        double BC = Math.sqrt((points[2] - points[4]) * (points[2] - points[4]) + (points[3] - points[5]) * (points[3] - points[5]));
        double CD = Math.sqrt((points[4] - points[6]) * (points[4] - points[6]) + (points[5] - points[7]) * (points[5] - points[7]));
        double DA = Math.sqrt((points[6] - points[0]) * (points[6] - points[0]) + (points[7] - points[1]) * (points[7] - points[1]));
        double BD = Math.sqrt((points[6] - points[2]) * (points[6] - points[2]) + (points[7] - points[3]) * (points[7] - points[3]));
        double AC = Math.sqrt((points[0] - points[4]) * (points[0] - points[4]) + (points[1] - points[5]) * (points[1] - points[5]));
        double ABD = AB * AB + DA * DA - BD * BD;
        double ABC = AB * AB + BC * BC - AC * AC;
        double CDB = CD * CD + BC * BC - BD * BD;
        double CDA = CD * CD + DA * DA - AC * AC;
        double A = Math.acos((ABD) / (2 * AB * DA));//"/"后面要加括号!
        double B = Math.acos((ABC) / (2 * AB * BC));
        double C = Math.acos((CDB) / (2 * BC * CD));
        double D = Math.acos((CDA) / (2 * CD * DA));
        judge[0] = Math.abs(A + B + C + D - 2 * Math.PI) < 0.0001;//判断是否为凸四边形(判断是否相等要加绝对值)
        if (judge[0]) {
            judge[1] = Math.abs(A - C) < 0.0001 && Math.abs(B - D) < 0.0001;//判断平行四边形
        }
        if (judge[1]) {
            judge[2] = Math.abs(AB - BC) < 0.0001;//菱形
            judge[3] = Math.abs(A - Math.PI / 2) < 0.0001;//矩形
        }
        if (judge[2]) {
            judge[4] = Math.abs(BC - CD) < 0.0001;//正方形
        }
        return judge;
    }

---------------------------------------------------------------------------------------------------------------------------------------------

 

 

踩坑心得:

计算除法时,我们一定要在“/”后加上括号防止出错。

-----------------------------------------------------------------------------------------------------------------------------------------------------

 

 

②:choice==2

这里我们仍是根据“ boolean[] judge = calculation.judgeQuadrilateral(point);  ”语句判断四边形类型,方法还calculation.judgeQuadrilateral(point);  

这段代码与“choice == 1”类似,我就不贴了。

----------------------------------------------------------------------------------------------------------------------------------------------------

 

③: choice == 3

这里计算的是面积和周长,我的思路:

计算周长的算法很简单,求边长再相加即可,用到了余弦定理

计算面积:将四边形分成两个三角形之后,使用向量积计算

 

原理:S = (1 / 2) * a * b * sinC, 正好是向量积绝对值的二分之一

 

注意:题目要求我们对超出三位小数点的保留三位小数。 

 

核心代码:

 public double areaTu(Integer[] points){//计算面积,利用向量积
        double area1 = Math.abs((points[2] - points[0]) * (points[5] - points[1]) - (points[4] - points[0]) * (points[3] - points[1])) / 2.0;
        double area2 = Math.abs((points[4] - points[0]) * (points[7] - points[1]) - (points[6] - points[0]) * (points[5] - points[1])) / 2.0;
        return (int)(((area1 + area2) * 1E3) + 0.5) / 1E3;
    }
if (judge[0]) {
                            double length = calculation.zhouchang(point);
                            System.out.println(judge[0] + " " + length + " " + calculation.areaTu(point));
                        } else{
                            System.out.println("false " + calculation.zhouchang(point) + " " + calculation.areaAo(point));
                        }

 

 

踩坑心得:

这里的心得很怪,因为我发现如果用1E3就可以得到三位小数,但是1e3就不行,我在网上也找了很多资料,目前尚未解决...

-----------------------------------------------------------------------------------------------------------------------------------------------------------

 

 

④.choice == 4

这里是判断直线与四边形的交点,并且如果有两个交点还要输出面积:

我的思路:

对于凸四边形,我认为还是很好解决的:

计算出小的三角形面积,在用四边形面积减去小三角型面积即可,比较大小之后就可输出结果了。

但是关于凹四边形的相关代码的实现,我没有想到什么方法,所以这部分代码没有写全。

Integer[] point4 = new Integer[8];
                            for(int i = 0; i < 8; i++){
                                point4[i] = point[i + 4];
                            }
                            calculation.isIntersect(point4, point[0], point[1], point[2], point[3]);
if((isA == 0 && isB == 0) || (isB == 0 && isC == 0) || (isC == 0 && isD == 0) || (isD == 0 && isA == 0)){
                System.out.println("The line is coincide with one of the lines");
            }else if(isA * isB * isC * isD < 0){//有两个交点
                double area = areaTu(points);

            }else if((isA == 0 && isC == 0) || (isB == 0 && isD == 0)){//对角线分割
                double area1, area2;
                if(isA == 0){//对角线AC分割
                    area1 = Math.abs((points[2] - points[0]) * (points[5] - points[1]) - (points[4] - points[0]) * (points[3] - points[1])) / 2.0;
                    area2 = Math.abs((points[4] - points[0]) * (points[7] - points[1]) - (points[6] - points[0]) * (points[5] - points[1])) / 2.0;
                }else{
                    area1 = Math.abs((points[2] - points[0]) * (points[7] - points[1]) - (points[6] - points[0]) * (points[3] - points[1])) / 2.0;
                    area2 = Math.abs((points[2] - points[4]) * (points[7] - points[5]) - (points[6] - points[4]) * (points[3] - points[5])) / 2.0;
                }
                if(area1 > area2){
                    System.out.println("2 " + area1 + " " + area2);
                }else{
                    System.out.println("2 " + area2 + " " + area1);
                }
            }

 

 

 

【改进意见】

1.要有自定义的Point类,Line类,triangle类,四边形类

2.自定义方法之间要独立,即不受约束的调用,如果调用A方法时要先调用B方法,这种代码就比较差了。

 

----------------------------------------------------------------------------------------------------------------------------------------------------------

第三题:

这一题很像java编程的经典例题,实现起来不难,但是有考到了很多知识点:

首先,我们自定义一个BankBusiness类,在类中定义属性和方法:

public static String bankName = "中国银行";
    private String name;//账户名
    private String password;//密码
    private double balance;//余额

如果类中有带参构造器时,我们最好也提供一个空参构造器,这样可以避免一些潜在的麻烦:
举个例子:如果定义一个类继承于BankBusiness类,如果你没有显示地使用super(...),那么子类会自动调用父类的空参构造器,所以这个时候如果父类没有空参构造器的话就会报错。

----------------------------------------------------------------------------------------------------

 

 

一个小小的踩坑心得(忘记是什么时候踩的,但既然说到了我就和大家分享吧):

子类不会自动调用父类的带参构造器。

比如:Student(String name){

  }

这里继承于People,并且people类中有形参为String name的构造器,但是这样写十错误的,我们必须以super(name)来调用;

------------------------------------------------------------------------------------------------

 

核心代码:

public BankBusiness(){

    }

    public BankBusiness(String name, String password){//开户
        this.name = name;
        this.password = password;
        this.balance = 0;

    }

 

接下来都是一些很简单的自定义方法,在此我也不做过多赘述,因为代码都简单,我就不贴了。

 

-------------------------------------------------------------------------------------------------

 

 

【慕课作业】

这次的作业考察了子父类的关系,即继承性以及方法的重写

代码的实现很简单,即添加一个MP3子类继承于Item类,再加上特有的属性:private String singer,提供带参构造器以及重写print()方法即可

 

 

核心代码:

 public class MP3 extends Item{
   private String singer;

   public MP3(String title, String singer, int playingTime, String comment){
       super(title, playingTime, false, comment);
       this.singer = singer;
   }

   public void print(){
       System.out.println("MP3: " + title + " ,singer: " + singer + " ,playingTime: " + playingTime + " ,comment: " + comment);
   }
}

---------------------------------------------------------------------------------------------------------------------------

 

 

 

【期中考试】

期中考试的代码虽然看起来长,但实际上难度不大,自定义的方法里的代码都比较简单。

由于第三题是结合了前两题的代码,在此我分析第三题即可:

 

首先我们会用到ArrayList<E>,这个和Arrays最大第区别在于他可以动态构建一个数组,也就是说,我们在使用是不用指定元素个数:

 例如:ArrayList<Element> elementList = null;

注意:这里的E指的是引用对象,代表这个list里面都是E型的对象,我们是不可以放基本数据类型的。

---------------------------------------------------------------------------------------------------

 

 

其次,我们还使用了抽象类:

abstract class Element{
    public abstract void display();
}

首先我们要知道的是,抽象类中除了抽象方法,也可以有非抽象类的方法;但是抽象方法一定要在抽象类中。

举个不太恰当的比例,小王一定是老王生的,但是老王除了小王也可以有别的孩子,这里的小王相当于抽象方法,老王相当于抽象类。

并且抽象方法只有声明,继承于该抽象类的子类的只有重写了抽象方法才可以实例化,否则也是一个抽象类。

------------------------------------------------------------------------------------------------------------------

 

 

自定义类中大多均为get和set方法,以及一些show()方法打印属性,难度不高。

 

踩坑心得:

在增删改查的删中,我们要注意元素全部删除完的情况,即在删之前先判断这个列表是否为空,如果是,就退出程序;否则继续执行删除动作:

核心代码:

public void remove(int index){
        if(elements.isEmpty()){
            System.exit(0);
        }
        if(index >= 0 && index <= elements.size() - 1) {
            elements.remove(index);
        }
    }

注:这里的exit(0)指的是正常退出程序

 

--------------------------------------------------------------------------------------------------------------

 

三、改进意见:

自定义方法之间要独立调用,即没有限制和约束调用,如果调用A方法时要先调用B方法,这种代码就比较差了。比如我在PTA第四题里就有很多复合调用,这种写法显然不好,代码的复用性也不高。

----------------------------------------------------------------------------------------------------------------------------------------

 

四、总结:

对于本阶段(7-10周)的学习,我学到了:

1.继承和多态的使用

2.抽象类和抽象方法的使用

3.泛型ArrayList<E>的使用

我认为在我提高代码复用性方面要进一步学习与研究,避免方法内部嵌套调用别的方法,希望自己的代码更加灵活。(革命尚未成功,同志仍需努力)

改进建议及意见:

希望老师们可以在每一次的PTA大作业结束之后分享题目的源码。通过自己的代码和老师代码的对比,我们可以更加直观地看出自己代码的不足,也可以学习老师的编程风格。

 

------------------------------------------------------------------------------------------------------

本次的博客到这里就全部结束了,感谢各位的阅读~~~

标签:总结性,java,abs,double,代码,Blog,points,Math,String
来源: https://www.cnblogs.com/Crystal0421/p/16162798.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有