编程语言
首页 > 编程语言> > java总结性Blog-2

java总结性Blog-2

作者:互联网

一、前言:

【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