(一)、前言
- 题目集四:
7-1:识蛟龙号载人深潜,立科技报国志(II)(正则表达式)
难度:1
知识点:正则表达式的使用
7-2: 点线形系列4-凸四边形的计算
难度:7
知识点:正则表达式的使用,建立点线面的类解决问题
7-3: 设计一个银行业务类
难度:2
知识点:构造实现各种功能的方法
- 期中考试
7-1 :点与线(类设计)
难度:2
知识点:类的封装
7-2 :点线面问题重构(继承与多态)
难度:4
知识点:对题目的类设计进行重构,以实现继承与多态的技术性需求
7-3 :点线面问题再重构(容器类)
难度:4
知识点:对题目的类设计进行重构,增加容器类保存点、线、面对象,并对该容器进行相应增、删、遍历操作
- 题目集五
7-1 :点线形系列5-凸五边形的计算
难度:10
知识点:五边形的类的设计,凸五边形的判断,凸多边形与直线的位置关系,,凸多边形被直线切割后的面积问题,凸多边形与凸多边形的位置关系
(二)、设计与分析
4-7-1题目分析:如下代码,本题中要识别出一段话中的所有数字,用到正则表达式中的"\\D+",用字符串的split方法将非数字剔除,留下数字储存在数组中,从而解决问题。
(注:大写D表示非数字,小写d表示数字)
do { int yes = 0; long sum = 0; s = input.nextLine(); if(s.equals("end"))break; String [] str = s.split("\\D+"); for(int i = 0; i < str.length; i++) { if(!str[i].equals("")) { yes = Integer.parseInt(str[i]); sum = sum + yes; } } System.out.println(sum); }while(s!="end");
4-7-2题目分析:
1:格式化实数的输出
输出的数据若小数点后超过3位,只保留小数点后3位,多余部分采用四舍五入规则进到最低位。小数点后若不足3位,按原始位数显示,不必补齐。
(例如:1/3的结果按格式输出为 0.333,1.0按格式输出为1.0)
如下代码,创建OutFormat的类,通过设置保留小数位的方法输出一定精度的实数;
在DecimalFormat df = new DecimalFormat("#.000")中括号里#.后几个零即为保留的精度位数;
但是要注意添加包:
import java.text.DecimalFormat;
class OutFormat { //按要求格式化实数的输出。 public static Double doubleFormat(double b) { DecimalFormat df = new DecimalFormat("#.000"); Double output = Double.valueOf(df.format(b)); return output; } }
2.判断输入点是否重合的方法
如下代码,我设计了两个判断点是否重合的方法,repeat判断输入的两个相邻的点是否重合,repeat2判断所有的输入的点是否重合;
方法二与冒泡排序法类似,但是要 zuobiao) { boolean repeat = false ; for(int i = 0; i < zuobiao.size()-1; i++) if(zuobiao.get(i).equals(zuobiao.get(i+1)) ) { repeat = true; break; } return repeat; } static int repeat2(ArrayList<Point> zuobiao) { int repeat2 = 0; out: for(int i=0; i<zuobiao.size(); i++) for(int j=i+1; j<zuobiao.size(); j++) if(zuobiao.get(i).equals(zuobiao.get(j))) { repeat2 = i; break out; } return repeat2; }
3:判断两条线是否平行的方法
判断两线平行不可忽略的一点是要考虑斜率不存在的情况
public boolean haveslope(Point a, Point b) { Line(a,b); if(this.p1.getx()==this.p2.getx()) return false; else return true; } public double slope(Point a, Point b) { Line(a,b); return ((this.p1.gety()-this.p2.gety())/(this.p1.getx()-this.p2.getx())); }
//两条线是否平行 public boolean parallel(Point c, Point d) { Line ll = new Line(c, d); if(!this.haveslope(p1,p2)&&!ll.haveslope(c,d)) return true; else if(this.haveslope(p1,p2)&&ll.haveslope(c,d)&&this.slope(p1,p2)==ll.slope(c,d)) return true; else return false; }
4.判断是否为凸四边形的方法
这里我思前想后用了许多数学方法,都不能得到很好的解决,经过多次对凸四边形与凹四边形特点的分析,发现从凹四边形面积较小,可由两个三角形相减得到,而凸四边形无论怎样分割成三角形,都是两个三角形面积之和组成凸四边形的面积,从而解决问题,如下代码。
//判断是否为凸四边形 public boolean tuside(Point a,Point b, Point c,Point d) { Side3 s1 = new Side3(a,b,c); Side3 s2 = new Side3(a,d,c); Side3 s3 = new Side3(a,b,d); Side3 s4 = new Side3(c,b,d); if(s1.S(a, b, c)+s2.S(a, d, c)==s3.S(a, b, d)+s4.S(c, d, b)) return true; else return false; }
5:计算四边形面积的方法
如下代码,凸四边形的面积容易得到,但是凹四边形比较难琢磨,在不断搜索的与尝试过程中,运用海伦公式发现并不能解决问题(海伦公式虽简便,但不适用于凹四边形;
分析凹四边形面积各种切分过后,发现只要是按顺序输入的构成四边形的四个点,计算前三点与后三点(第1、2、3 和 2、3、4的点)所构成的三角形的面积相加,以及第1、2、4 和 2、3、4 的点所构成
的三角形的面积相加,比较出较小的一组三角形面积之和即为凹四边形的面积;
但是我这种方法不能用于计算不按顺序输入的四点构成凹四边形的面积,存在不足,所以这个测试点没有拿到很多分。
//四边形面积 public float S(Point a,Point b, Point c,Point d) { if(this.tuside(a, b, c, d)) {//凸四边形的面积 return this.St(a, b, c, d); } else { // double p = (this.C(a, b, c, d)/2); // double aa = a.getDistance(b); // double bb = b.getDistance(c);//怎么回事海伦公式用不了吗? // double cc = c.getDistance(d); // double dd = c.getDistance(a); // return (float)(Math.sqrt((p-aa)*(p-bb)*(p-cc)*(p-dd))); Side3 s1 = new Side3(a,b,c); Side3 s2 = new Side3(a,d,c); Side3 s3 = new Side3(a,b,d); Side3 s4 = new Side3(c,b,d); float sa = (float)(s1.S(a, b, c)+s2.S(a, d, c)); float sb = (float)(s3.S(a, b, d)+s4.S(c, d, d)); float ss; if(sa > sb) ss = sb; else ss = sa; return ss; } }
6.判断点与多边形的位置关系
这里我为了区分点在多边形内部,外部,以及边上,采用返回类型为int的方法,区分与四边形或三角形的位置关系
//判断点在图形里 不在0 //返回值:四边形内1 外2 边3 // 三角形内4 外5 边6 public int pointinside(Point x,Point a,Point b, Point c,Point d ) { int yes = 0; Line l12 = new Line(a, b); Line l23 = new Line(b, c); Line l34 = new Line(c, d); Line l14 = new Line(a, d); Line l13 = new Line(a, c); Line l24 = new Line(b, d); if(this.tuside(a, b, c, d)) if(l12.pointinline(x)||l23.pointinline(x)||l34.pointinline(x)||l14.pointinline(x)) yes = 3; else if(this.inside4(x, a, b, c, d)) yes = 1; else yes = 2; else if(this.triangle(a, b, c, d)!=0) { switch(this.triangle(a, b, c, d)) { case 2: if(l13.pointinline(x)||l14.pointinline(x)||l34.pointinline(x)) yes = 6; else if(this.inside3(x, a, c, d)) yes = 4; else yes = 5; break; case 3: if(l12.pointinline(x)||l14.pointinline(x)||l24.pointinline(x)) yes = 6; else if(this.inside3(x, a, b, d)) yes = 4; else yes = 5; break; case 4: if(l13.pointinline(x)||l12.pointinline(x)||l23.pointinline(x)) yes = 6; else if(this.inside3(x, a, b, c)) yes = 4; else yes = 5; break; } } return yes; }
期中考试分析:
一二题较简单,为一般的类的设计,将点线面的类进行封装;
第三题分析:
增加容器类保存点、线、面对象,并对该容器进行相应增、删、遍历操作;
运用Element类型的ArrayList数组的增、删、遍历功能进行操作;
new ArrayList<Element>();; GeometryObject(){ } public void add(Element element){ list.add(element); } public void remove(int index) { list.remove(index); } public ArrayList<Element> getList(){ return this.list; } }
子类继承父类的属性及方法:
class Point extends Element{ private double x; private double y; public Point() { } public Point(double a,double b) { this.x = a; this.y = b; } public void setX(double a) { this.x = a; } public void setY(double b) { this.y = b; } public double getX() { return this.x; } public double getY() { return this.y; } public void display() { System.out.printf("(%.2f,%.2f)\n",this.getX(),this.getY()); } } class Line extends Element{ private Point p1; private Point p2; private String color; public Line() { } public Line(Point a, Point b, String c) { this.p1 = a; this.p2 = b; this.color = c; } public Point getPoint1() { return this.p1; } public void setPoint1(Point a) { this.p1 = a; } public Point getPoint2() { return this.p2; } public void setPoint2(Point a) { this.p2 = a; } public String getColor() { return this.color; } public void setColor(String s) { this.color = s; } public double getDistance() { return Math.sqrt(Math.pow(this.p1.getX()-this.p2.getX(), 2)+Math.pow(this.p1.getY()-this.p2.getY(), 2)); } public void display() { System.out.print("The line's color is:"); } }
但是第三题有一些困难,如下图,remove all 和remove first相关的测试点都没有得到分;
后来分析想想,觉得是删除元素位置的特殊性(收尾操作应该特殊处理)
5-7-1分析:
判断是否为凸五边形,在不断的分析与查找的过程中,决定采用凸五边形角度和为540的性质进行设计;
但是要注意的是Math.acos()返回的是弧度制的角,需要进一步采用Math.toDegrees()进行度数的转换。
如下代码。
//计算当前点与另两点的射线组成的角度 public double angle(Point m,Point n) { double a = this.getDistance(m); double c = m.getDistance(n); double b = this.getDistance(n); return Math.toDegrees(Math.acos((a*a+b*b-c*c)/(2*a*b))); }
依据角度计算是否为凸五边形:
//判断是否为凸五边形 public boolean tuSide5() { boolean yes = false; double anglesum = (double)(p1.angle(p2, p5)+p2.angle(p1, p3)+p3.angle(p2, p4)+p4.angle(p3, p5)+p5.angle(p4, p1)); if(anglesum>=540) yes = true; else yes = false; return yes; }
五边形的面积可切分成四边形与三角形来求得:
//计算周长 public double C() { return (p1.getDistance(p2)+p2.getDistance(p3)+p3.getDistance(p4)+p4.getDistance(p5)+p5.getDistance(p1)); } //计算面积 public double S() { Side4 s1 = new Side4(p1,p2,p3,p4); Side3 s2 = new Side3(p1,p4,p5); return (s1.S(p1, p2, p3, p4)+s2.S(p1, p4, p5)); }
(三)、踩坑心得
1.没有注意 double和float的数据类型,虽然说都是表示浮点数,之前一直以为只是精度不同占据内存空间不同而已,没想到小数默认是double类型,用float时需要进行强制转换;
2.字符串的substring用法没有记清楚,s.substring(a,b)的返回值是截取的字符串s从a到b-1这一部分,而非包括s.charAt(b);
3.在做题过程中根据next()与nextLine()的区别,以为自作聪明可以用循环内的next()来获取每一个以空格结尾的坐标,却没有考虑到如果输入的以空格结尾的字符串根本不符合坐标格式,就不能跳过来识别下一个字符串了;
4.运行结果输出了NaN这个不明所以的东西,一开始还以为是我手滑不小心打的字母,经过一步步debug还是百思不得其解,它为什么就给我输出这个鬼东西,在搜集一些资料才发现是得出的结果就是有问题的,NaN表示Not a Number,就是说可能出现了数据极其小或者极其大或者无法运算的情况,最后才发现是我没考虑到之前斜率不存在的情况;
5:没有根据数据是否为有限小数来控制输出格式,也不知道怎么判断一个数是否为有限小数,在请教几位同学之后才知道,其实可以转化成(x*1000000%10)是否等于0的问题。
(四)、改进建议
- 可以多学习一些处理点线面的数据更为方便的数学技巧,能避免很多问题,实质性内容更明显。
- 多去找问题发现问题,反思总结前面代码是否合适,不要怕推翻重来。
- 多考虑主类和子类的关系,处理好各种调用,思路和表达都要清晰有条理,代码才能看得舒心,用的放心。
- 注意double精度问题,时刻考虑将运算结果强制转化成float类型,否则数据不准确
- 多查找资料多请教同学,掌握的越多,大脑储备更全,以应对解决任何未知问题。
(五)总结
这次实验计我学习到了很多,也发现了自己的很多问题,以及认识到了一些基础知识的缺乏。认识问题不够透彻,靠主观臆断试错,而不是先查询资料搞清楚.通过此次实验,我深刻认识到Java基本知识的重要性,并且学习到很多有用的知识,还锻炼了更加仔细探究问题的能力。在调试过程中,我发现有很多不懂的地方,绞尽脑汁也不清楚自己问题出现在哪,只能查找相关资料一步一步慢慢学习新知识,并将旧知识加以巩固。认识到我的各种不足后,我也会更加细致,多学习,多积累,遇到不懂的多借助网上资源进行自学。此外,在学习方法方面,我认识到应该提前清晰地计划好要解决的部分,不能将许多bug堆在一起等着之后再一个一个解决,否则会酿成不可预料无法挽救的可怜局面。总之,学习编程要时刻保持严谨的学术态度,细致认真脚踏实地才能有所建树.
标签:p1,return,Point,double,Blog,yes,public From: https://www.cnblogs.com/balabala-la/p/16839427.html