Blog1:nchu-software-oop-2022-1~3
(1) 前言
针对在完成三次作业过程中产生的问题进行总结与分析。
三次作业一共十五(9+3+3)道题目,其中前两次难度较为简单,第三次复杂程度飞跃式上涨。
其中,涉及到java语言中基本的输入输出语句、if/else判断语句、for/while循环语句、String类型字符串调用字符、正则表达式和split拆分函数、各类型数组定义和使用以及类和对象等知识点。
其中最最需注意的double型数据精度计算带来的误差!!!!!!!!!!!!
(2) 设计与分析
重点题目1:(Pta1-9)
7-7 判断三角形类型
输入三角形三条边,判断该三角形为什么类型的三角形。
输入格式:
在一行中输入三角形的三条边的值(实型数),可以用一个或多个空格或回车分隔,其中三条边的取值范围均为[1,200]。
输出格式:
(1)如果输入数据非法,则输出“Wrong Format”;
(2)如果输入数据合法,但三条边不能构成三角形,则输出“Not a triangle”;
(3)如果输入数据合法且能够成等边三角形,则输出“Equilateral triangle”;
(3)如果输入数据合法且能够成等腰直角三角形,则输出“Isosceles right-angled triangle”;
(5)如果输入数据合法且能够成等腰三角形,则输出“Isosceles triangle”;
(6)如果输入数据合法且能够成直角三角形,则输出“Right-angled triangle”;
(7)如果输入数据合法且能够成一般三角形,则输出“General triangle”。
********************************************************************************************************************************************************************************************
这道题目的难度并没有很大,主要根据各类三角形特征给出不同的三角形三边限制,通过if/else判断语句完成。
源码如下:
import java.util.Scanner; public class Main
{
public static void main(String[] args)
{
Scanner x=new Scanner(System.in);
double a=x.nextDouble();
double b=x.nextDouble();
double c=x.nextDouble(); if((a<1||a>200)||(b<1||b>200)||(c<1||c>200))
System.out.print("Wrong Format");
else if((a+b<=c)||(a+c<=b)||(b+c<=a))
System.out.print("Not a triangle");
else if(a==b&&b==c)
System.out.print("Equilateral triangle");
else if(((a*a+b*b-c*c<0.01)||(a*a+c*c-b*b<0.01)||(b*b+c*c-a*a<0.01))&&((a==b&&a!=c)||(b==c&&b!=a)||(a==c&&a!=b)))/
System.out.print("Isosceles right-angled triangle");
else if((a==b&&a!=c)||(b==c&&b!=a)||(a==c&&a!=b))
System.out.print("Isosceles triangle");
else if((a*a+b*b-c*c==0)||(a*a+c*c-b*b==0)||(b*b+c*c-a*a==0))
System.out.print("Right-angled triangle");
else
System.out.print("General triangle");
}
}
由于没有使用面向对象的方法来写,将代码都写在主函数中,导致复杂度过高。
本题由于是判断三角形形状,if/else语句过多,导致代码质量不高,有待改进。
*********************************************************************************************************************************************************************************************
重点题目2:(pta2-2)
7-2 串口字符解析
RS232是串口常用的通信协议,在异步通信模式下,串口可以一次发送5~8位数据,收发双方之间没有数据发送时线路维持高电平,相当于接收方持续收到数据“1”(称为空闲位),发送方有数据发送时,会在有效数据(5~8位,具体位数由通信双方提前设置)前加上1位起始位“0”,在有效数据之后加上1位可选的奇偶校验位和1位结束位“1”。请编写程序,模拟串口接收处理程序,注:假定有效数据是8位,奇偶校验位采用奇校验。
输入格式:
由0、1组成的二进制数据流。例如:11110111010111111001001101111111011111111101111
输出格式:
过滤掉空闲、起始、结束以及奇偶校验位之后的数据,数据之前加上序号和英文冒号。
如有多个数据,每个数据单独一行显示。
若数据不足11位或者输入数据全1没有起始位,则输出"null data",
若某个数据的结束符不为1,则输出“validate error”。
若某个数据奇偶校验错误,则输出“parity check error”。
若数据结束符和奇偶校验均不合格,输出“validate error”。
如:11011或11111111111111111。
例如:
1:11101011
2:01001101
3:validate error
***************************************************************************************************
这道题目使用字符串类型输入一串信号,首先对输入的字符串进行格式分析(数据不足11位或者输入数据全1没有起始位,则输出"null data"),然后开始在字符串中使用charAt()找出字符串中的“0”,并判断是否满足数据11位。若满足则继续判断8位数字是否符合要求。不符合则输出相应的error,符合则输出8位数据。
源码下图:
import java.util.Scanner;
public class Main
{
public static void main(String[] args)
{
Scanner x=new Scanner(System.in);
String a=x.next();
int length=a.length();
int shu=1,ci=0;
if(length<11)
{
System.out.print("null data");
return;
} int k=-1;
for(int i1=0;i1<length;i1++)
{
if(a.charAt(i1)=='0')
k=0;
}
if(k==-1)
{
System.out.print("null data");
return;
}
for(int i=0;i<length;)
{
if(length-i<10)
break;
else if(a.charAt(i)=='1')
i++;
else if(a.charAt(i)=='0')
{
int x1,x2;
if(a.charAt(i+10)=='1')
x1=1;
else
x1=0;
int num=0,flag=-1;
for(int n=1;n<9;n++)
{
if(a.charAt(i+n)=='1')
num++;
}
if(num%2==1)
flag=1;
else
flag=0;
if((flag==1&&a.charAt(i+9)=='0')||(flag==0&&a.charAt(i+9)=='1'))
x2=1;
else
x2=0;
if(x1==0&&x2==1)
{
System.out.print(shu+":");
shu++;
System.out.println("validate error");
}
else if(x1==1&&x2==0)
{
System.out.print(shu+":");
shu++;
System.out.println("parity check error");
}
else if(x1==0&&x2==0)
{
System.out.print(shu+":");
shu++;
System.out.println("validate error");
}
else if(x1==1&&x2==1)
{
System.out.print(shu+":");
shu++;
for(int m=1;m<9;m++)
System.out.print(a.charAt(i+m));
System.out.print("\n");
}
i=i+11;
}
}
}
}
由于没有使用面向对象的方法来写,将代码都写在主函数中,导致复杂度过高,导致代码质量不高,有待改进。
应该将for语句和判断语句单独函数。
*******************************************************************************************************************************************************************************************************
重点题目3:(pta3-1)
输入连个点的坐标,计算两点之间的距离
输入格式:
4个double类型的实数,两个点的x,y坐标,依次是x1、y1、x2、y2,两个点的坐标之间以空格分隔,每个点的x,y坐标以英文“,”分隔。例如:0,0 1,1或0.1,-0.3 +3.5,15.6。
若输入格式非法,输出"Wrong Format"。
若输入格式合法但坐标点的数量超过两个,输出“wrong number of points”。
输出格式:
计算所得的两点之间的距离。例如:1.4142135623730951
*********************************************************************************************************************************************************************************************************
这道题目需要用到正则表达式,首先将输入的字符串用split()函数,从空格“ ”处拆分开,将拆开后的每一项与对应的坐标正则表达式进行matches,匹配出"Wrong Format"。
同时,通过length,取得拆分段数,若length不为2,则“wrong number of points”。
最后用Math.sqrt()和Math.pow()算出两点间距离即可。(由于本题复杂程度不高,所以没有采用类和对象的方法写)
源码如下:
import java.util.Scanner; public class Main
{
public static void main(String[] args)
{
Scanner in=new Scanner(System.in);
String a=in.nextLine();
int length1=a.length(); int num3=0;
String[] tokens=a.split(" ");
int length2=tokens.length;
for(int j=0;j<length2;j++)
{
if(!tokens[j].matches("^[+-]?(0|(0\\.\\d+)?|[1-9][0-9]*(\\.\\d+)?),[+-]?(0|(0\\.\\d+)?|[1-9][0-9]*(\\.\\d+)?)$"))
num3=1;
}
if(num3==1)
{
System.out.print("Wrong Format");
return;
}
else if(num3==0)
{
if(length2!=2)
{
System.out.print("wrong number of points");
return;
}
else
{
String[] A=tokens[0].split(",");
String[] B=tokens[1].split(",");
double l;
double x1=Double.valueOf(A[0]);
double y1=Double.valueOf(A[1]);
double x2=Double.valueOf(B[0]);
double y2=Double.valueOf(B[1]);
l=Math.sqrt(Math.pow(x1-x2,2)+Math.pow(y1-y2,2));
System.out.print(l);
}
}
}
}
由于没有使用面向对象的方法来写,将代码都写在主函数中,导致复杂度过高,导致代码质量不高,有待改进。
应该将for语句和判断语句单独函数。
*******************************************************************************************************************************************************************************************************
重点题目4:
用户输入一组选项和数据,进行与直线有关的计算。选项包括:
1:输入两点坐标,计算斜率,若线条垂直于X轴,输出"Slope does not exist"。
2:输入三个点坐标,输出第一个点与另外两点连线的垂直距离。
3:输入三个点坐标,判断三个点是否在一条线上,输出true或者false。
4:输入四个点坐标,判断前两个点所构成的直线与后两点构成的直线是否平行,输出true或者false.
5:输入四个点坐标,计算输出前两个点所构成的直线与后两点构成的直线的交点坐标,x、y坐标之间以英文分隔",",并输出交叉点是否在两条线段之内(不含四个端点)的判断结果(true/false),判断结果与坐标之间以一个英文空格分隔。若两条线平行,没有交叉点,则输出"is parallel lines,have no intersection point"。
输入格式:
基本格式:选项+":"+坐标x+","+坐标y+" "+坐标x+","+坐标y。
例如:1:0,0 1,1
如果不符合基本格式,输出"Wrong Format"。
如果符合基本格式,但输入点的数量不符合要求,输出"wrong number of points"。
不论哪个选项,如果格式、点数量都符合要求,但构成任一条线的两个点坐标重合,输出"points coincide",
输出格式:
见题目描述。
*******************************************************************************************************************************************************************************************************
在写这题的时候创立三个类,一个点Point类、一个线Line类和一个主类。
class Point{
double x;double y;//点的横纵坐标
}
class Line
{
double k;//斜率
double a;double b;double c;//直线一般式系数abc(使用一般式可以不用去特殊考虑斜率不存在的情况)
}
和上一题一样还是先从空格处分开,再与正则表达式相匹配。
但在后面将坐标数据存入的时候,String[] arr=a.split(":| |,");再重新拆分并且三个符号一起拆,这样可以避免字符串被拆到不同的数组里面带来不便。
在主类中用switch函数,分情况写每种选项下的情况。将一些主要的方法写在了线类里方便调用。
源码如下:
import java.util.Scanner; class Point
{
double x;
double y;
}
class Line
{
double k;//斜率
double a;
double b;
double c; public void L(Point A,Point B)
{
a=B.y-A.y;
b=A.x-B.x;
c=B.x*A.y-A.x*B.y;
}
public boolean chonghe(Point A,Point B)//判断重合
{
if(A.x==B.x&&A.y==B.y)
{
System.out.print("points coincide");
return true;
}
else
return false;
}
public void xielv(Point A,Point B)//求斜率
{
if(A.x==B.x)
System.out.print("Slope does not exist");
else
System.out.print((B.y-A.y)/(B.x-A.x));
}
public void juli(Point A,Line l)//点到直线距离
{
double D;
D=Math.abs(a*A.x+b*A.y+c)/Math.sqrt(Math.pow(a,2)+Math.pow(b,2));
System.out.print(D);
}
public void shuyu(Point A,Line l)//点是否在直线上
{
if(A.x*l.a+A.y*l.b+l.c==0)
System.out.print("true");
else
System.out.print("false");
}
public boolean pingxing(Line l1,Line l2)//判断是否平行
{
if(l1.b==0&&l2.b==0)
return true;
else if(l1.b!=0&&l2.b!=0&&(l1.a/l1.b==l2.a/l2.b))
return true;
else
return false;
}
public void jiaodian(Line l1,Line l2,Point P)//交点坐标
{
P.x=(l1.b*l2.c-l2.b*l1.c)/(l1.a*l2.b-l2.a*l1.b);
P.y=(l2.a*l1.c-l1.a*l2.c)/(l1.a*l2.b-l2.a*l1.b);
}
} public class Main
{
public static void main(String[] args)
{
Scanner x=new Scanner(System.in);
String a=x.nextLine(); int num = (int)a.charAt(0) - (int)'0'; String[] tokens=a.split(" ");
int length=tokens.length;
for(int i=0;i<length;i++)
{ if(i==0)
{
if(!tokens[i].matches("^\\d:[+-]?(0|(0\\.\\d+)?|[1-9][0-9]*(\\.\\d+)?),[+-]?(0|(0\\.\\d+)?|[1-9][0-9]*(\\.\\d+)?)$"))
{
System.out.print("Wrong Format");
return;
}
}
else if(i!=0)
{
if(!tokens[i].matches("^[+-]?(0|(0\\.\\d+)?|[1-9][0-9]*(\\.\\d+)?),[+-]?(0|(0\\.\\d+)?|[1-9][0-9]*(\\.\\d+)?)$"))
{
System.out.print("Wrong Format");
return;
}
}
} if((num==1&&length!=2)||((num==2||num==3)&&length!=3)||((num==4||num==5)&&length!=4))
{
System.out.print("wrong number of points");
return;
} String[] arr=a.split(":| |,");
switch(num)
{
case 1:
{
Point A=new Point();
Point B=new Point();
A.x=Double.valueOf(arr[1]);
A.y=Double.valueOf(arr[2]);
B.x=Double.valueOf(arr[3]);
B.y=Double.valueOf(arr[4]); Line l1=new Line();
if(!l1.chonghe(A,B))
l1.xielv(A,B);
break;
}
case 2:
{
Point A=new Point();
Point B=new Point();
Point C=new Point();
A.x=Double.valueOf(arr[1]);
A.y=Double.valueOf(arr[2]);
B.x=Double.valueOf(arr[3]);
B.y=Double.valueOf(arr[4]);
C.x=Double.valueOf(arr[5]);
C.y=Double.valueOf(arr[6]);
Line l1=new Line();
if(!l1.chonghe(B,C));
{
l1.L(B,C);
l1.juli(A,l1);
}
break;
}
case 3:
{
Point A=new Point();
Point B=new Point();
Point C=new Point();
A.x=Double.valueOf(arr[1]);
A.y=Double.valueOf(arr[2]);
B.x=Double.valueOf(arr[3]);
B.y=Double.valueOf(arr[4]);
C.x=Double.valueOf(arr[5]);
C.y=Double.valueOf(arr[6]);
Line l1=new Line();
if(!l1.chonghe(A,B)&&!l1.chonghe(A,C)&&!l1.chonghe(B,C))
{
l1.L(B,C);
l1.shuyu(A,l1);
}
break;
}
case 4:
{
Point A=new Point();
Point B=new Point();
Point C=new Point();
Point D=new Point();
A.x=Double.valueOf(arr[1]);
A.y=Double.valueOf(arr[2]);
B.x=Double.valueOf(arr[3]);
B.y=Double.valueOf(arr[4]);
C.x=Double.valueOf(arr[5]);
C.y=Double.valueOf(arr[6]);
D.x=Double.valueOf(arr[7]);
D.y=Double.valueOf(arr[8]);
Line l1=new Line();
Line l2=new Line();
if(!l1.chonghe(A,B)&&!l1.chonghe(C,D))
{
l1.L(A,B);
l2.L(C,D);
if(!l1.pingxing(l1,l2))
System.out.print("false");
else
System.out.print("true");
}
break;
}
case 5:
{
Point A=new Point();
Point B=new Point();
Point C=new Point();
Point D=new Point();
Point P=new Point();
A.x=Double.valueOf(arr[1]);
A.y=Double.valueOf(arr[2]);
B.x=Double.valueOf(arr[3]);
B.y=Double.valueOf(arr[4]);
C.x=Double.valueOf(arr[5]);
C.y=Double.valueOf(arr[6]);
D.x=Double.valueOf(arr[7]);
D.y=Double.valueOf(arr[8]);
Line l1=new Line();
Line l2=new Line();
if(!l1.chonghe(A,B)&&!l2.chonghe(C,D))
{
l1.L(A,B);
l2.L(C,D);
if(l1.pingxing(l1,l2))
System.out.print("is parallel lines,have no intersection point");
else
{
l1.jiaodian(l1,l2,P);
System.out.print(P.x+","+P.y+" ");
if((P.x==A.x&&P.y==A.y)||(P.x==B.x&&P.y==B.y)||(P.x==C.x&&P.y==C.y)||(P.x==D.x&&P.y==D.y))
System.out.print("false");
else
{
double PA=Math.sqrt(Math.pow(A.x-P.x,2)+Math.pow(A.y-P.y,2));
double PB=Math.sqrt(Math.pow(B.x-P.x,2)+Math.pow(B.y-P.y,2));
double PC=Math.sqrt(Math.pow(C.x-P.x,2)+Math.pow(C.y-P.y,2));
double PD=Math.sqrt(Math.pow(D.x-P.x,2)+Math.pow(D.y-P.y,2));
double AB=Math.sqrt(Math.pow(A.x-B.x,2)+Math.pow(A.y-B.y,2));
double CD=Math.sqrt(Math.pow(C.x-D.x,2)+Math.pow(C.y-D.y,2));
if((PA+PB-AB<0.000001)||(PC+PD-CD<0.000001))
System.out.print("true");
else
System.out.print("false");
}
}
}
break;
}
}
}
}
虽然使用了面向对象的方法,但是创建类是并没有创建的很完善。
另外,很多内容还是挤在一起,没有去单独构造成函数。
********************************************************************************************************************************************************************************************************
重点题目5:
用户输入一组选项和数据,进行与三角形有关的计算。选项包括:
1:输入三个点坐标,判断是否是等腰三角形、等边三角形,判断结果输出true/false,两个结果之间以一个英文空格符分隔。
2:输入三个点坐标,输出周长、面积、重心坐标,三个参数之间以一个英文空格分隔,坐标之间以英文","分隔。
3:输入三个点坐标,输出是钝角、直角还是锐角三角形,依次输出三个判断结果(true/false),以一个英文空格分隔,
4:输入五个点坐标,输出前两个点所在的直线与三个点所构成的三角形相交的交点数量,如果交点有两个,则按面积大小依次输出三角形被直线分割成两部分的面积。若直线与三角形一条线重合,输出"The point is on the edge of the triangle"
5:输入四个点坐标,输出第一个是否在后三个点所构成的三角形的内部(输出in the triangle/outof triangle)。
必须使用射线法,原理:由第一个点往任一方向做一射线,射线与三角形的边的交点(不含点本身)数量如果为1,则在三角形内部。如果交点有两个或0个,则在三角形之外。若点在三角形的某条边上,输出"on the triangle"
输入格式:
基本格式:选项+":"+坐标x+","+坐标y+" "+坐标x+","+坐标y。点的x、y坐标之间以英文","分隔,点与点之间以一个英文空格分隔。
输出格式:
基本输出格式见每种选项的描述。
异常情况输出:
如果不符合基本格式,输出"Wrong Format"。
如果符合基本格式,但输入点的数量不符合要求,输出"wrong number of points"。
如果输入的三个点无法构成三角形,输出"data error"。
注意:输出的数据若小数点后超过6位,只保留小数点后6位,多余部分采用四舍五入规则进到最低位。小数点后若不足6位,按原始位数显示,不必补齐。例如:1/3的结果按格式输出为 0.333333,1.0按格式输出为1.0
选项4中所输入线的两个点坐标重合,输出"points coincide",
**********************************************************************************************************************************************************************************************************
这题建立了三个类如下:
class Point{
double x;
double y;
int flag;//点是否在线段上(0不在1在)
public boolean pointchonghe()//判断两点重合
}
class Line{
double D;//线段距离
double a;//表达式系数a*x+b*y+c=0
double b;
double c;
public void L(Point A,Point B,Line l)//一般式系数
public void distanse(Point A,Point B,Line l)//求D
public boolean linechonghe(Line l1,Line l2)//判断是否两线重合
public boolean pingxing(Line l1,Line l2)//判断是否平行(有无交点)
public boolean sanjiaox(Line l1,Line l2,Line l3)//判断是否为三角形
public boolean dengyao(Line l1,Line l2,Line l3)//判断是否为等腰三角形
public boolean dengbian(Line l1,Line l2,Line l3)//判断是否为等边三角形
}
class triangle{
double l1;
double l2;
double l3;
double h;
double C;
double S;
double cosA;
double cosB;
double cosC;
int num;
public void h(Point A,Line l,triangle t)//点到直线距离(高)
public void zhouchang(triangle t)//周长
public void mianji(Point A,Point B,Point C,Line l,triangle t)//面积
public boolean pointwhere(Point A,Point B,Point C,Line lAB,Line lAC,Line lBC)//点A是否在线段BC上
public void jiaodiannum(Point A,Point B,Point C,Point D,Point E,Point P1,Point P2,Point P3,Line l1,Line l2,Line l3,Line l4,triangle t)//交点数(线和三角形)
public void jiaodian(Line l1,Line l2,Point O)//两条直线交点
public void zhongxin(Point A,Point B,Point C,Point O)//求重心坐标
public void cos(Line l1,Line l2,Line l3,triangle t)//cos
public boolean dunjiao(Line l1,Line l2,Line l3,triangle t)//判断是否钝角三角形
public boolean zhijiao(Line l1,Line l2,Line l3,triangle t)//判断是否直角三角形
public boolean ruijiao(Line l1,Line l2,Line l3,triangle t)//判断是否锐角三角形
}
字符串的输入和拆分方式,以及判非法输入,坐标赋值皆可延用上一题的内容。
计算直线与三角形交点数量:首先分别判断直线AB与三角形三边AB、AC、BC是否有交点(两条直线是否有交点),若有则求出交点坐标
再判断交点是否AB/AC/BC线段上(是否在三角形三个顶点处需特殊判断),以此来计算出交点数目
在 判断点A与三角形BCD关系时即选项5:也采用了线与三角形交点数量函数
分别判断AB/AC/AD与三角形的交点数量,如果都是两个交点,则说明点在三角形内部
在三角形上的情况即判断点是否在线段上,则在三角形外。
主类代码如下:
public class Main
{
public static void main(String[] args)
{
Scanner in=new Scanner(System.in);
String a=in.nextLine();
int num = (int)a.charAt(0) - (int)'0';//选项 String[] tokens=a.split(" ");
int length=tokens.length;
for(int i=0;i<length;i++)
{
if(i==0)
{
if(!tokens[i].matches("^\\d:[+-]?(0|(0\\.\\d+)?|[1-9][0-9]*(\\.\\d+)?),[+-]?(0|(0\\.\\d+)?|[1-9][0-9]*(\\.\\d+)?)$"))
{
System.out.print("Wrong Format");
return;
}
}
else if(i!=0)
{
if(!tokens[i].matches("^[+-]?(0|(0\\.\\d+)?|[1-9][0-9]*(\\.\\d+)?),[+-]?(0|(0\\.\\d+)?|[1-9][0-9]*(\\.\\d+)?)$"))
{
System.out.print("Wrong Format");
return;
}
}
} if(((num==1||num==2)&&length!=3)||(num==4&&length!=5)||(num==5&&length!=4))
{
System.out.print("wrong number of points");
return;
} String[] arr=a.split(":|,| "); Point A=new Point();
Point B=new Point();
Point C=new Point();
A.x=Double.valueOf(arr[1]);
A.y=Double.valueOf(arr[2]);
B.x=Double.valueOf(arr[3]);
B.y=Double.valueOf(arr[4]);
C.x=Double.valueOf(arr[5]);
C.y=Double.valueOf(arr[6]);
Line lAB=new Line();
Line lAC=new Line();
Line lBC=new Line();
lAB.distanse(A,B,lAB);
lAC.distanse(A,C,lAC);
lBC.distanse(B,C,lBC); switch(num)
{
case 1:
{
if(!lAB.sanjiaox(lAB,lAC,lBC))
System.out.print("data error");
else
{
if(!lAB.dengyao(lAB,lAC,lBC))
System.out.print("false ");
else
System.out.print("true ");
if(!lAB.dengbian(lAB,lAC,lBC))
System.out.print("false");
else
System.out.print("true");
}
break;
}
case 2:
{
if(!lAB.sanjiaox(lAB,lAC,lBC))
{
System.out.print("data error");
return;
}
triangle t=new triangle();
t.l1=lAB.D;
t.l2=lAC.D;
t.l3=lBC.D;
t.zhouchang(t);//求周长
System.out.print(Math.round(t.C*1000000)/(double)1000000);
System.out.print(" "); t.mianji(A,B,C,lBC,t);//求面积
System.out.print(Math.round(t.S*1000000)/(double)1000000);
System.out.print(" "); Point O=new Point();//求重心坐标
t.zhongxin(A,B,C,O);
System.out.print(Math.round(O.x*1000000)/(double)1000000);
System.out.print(",");
System.out.print(Math.round(O.y*1000000)/(double)1000000);
break;
}
case 3:
{
if(!lAB.sanjiaox(lAB,lAC,lBC))
{
System.out.print("data error");
return;
} triangle t=new triangle();
if(t.dunjiao(lAB,lAC,lBC,t))
System.out.print("true ");
else
System.out.print("false "); if(t.zhijiao(lAB,lAC,lBC,t))
System.out.print("true ");
else
System.out.print("false "); if(t.ruijiao(lAB,lAC,lBC,t))
System.out.print("true");
else
System.out.print("false");
break;
}
case 4:
{
if(A.pointchonghe(A,B))//判断AB是否重合
{
System.out.print("points coincide");return;
} Point D=new Point();
Point E=new Point();
D.x=Double.valueOf(arr[7]);
D.y=Double.valueOf(arr[8]);
E.x=Double.valueOf(arr[9]);
E.y=Double.valueOf(arr[10]); Line lCD =new Line();
Line lCE =new Line();
Line lDE =new Line();
lCD.distanse(C,D,lCD);
lCE.distanse(C,E,lCE);
lDE.distanse(D,E,lDE); if(!lCD.sanjiaox(lCD,lCE,lDE))//判断是CDE否为三角形
{
System.out.print("data error");return;
} lAB.L(A,B,lAB);
lCD.L(C,D,lCD);
lCE.L(C,E,lCE);
lDE.L(D,E,lDE); if(lAB.linechonghe(lAB,lCD)||lAB.linechonghe(lAB,lCE)||lAB.linechonghe(lAB,lDE))
{
System.out.print("The point is on the edge of the triangle");return;
} Point P1=new Point();
Point P2=new Point();
Point P3=new Point();
triangle t1=new triangle();
t1.jiaodiannum(A,B,C,D,E,P1,P2,P3,lAB,lCD,lCE,lDE,t1);
System.out.print(t1.num); triangle t2=new triangle();
if(t1.num==2)
{
t1.mianji(C,D,E,lDE,t1);
System.out.print(" ");
if(P1.flag==1&&P2.flag==1)//三角形CP1P2
{
Line lP1P2=new Line();
t2.mianji(C,P1,P2,lP1P2,t2);
}
else if(P1.flag==1&&P3.flag==1)
{
Line lP1P3=new Line();
t2.mianji(D,P1,P3,lP1P3,t2);
}
else if(P2.flag==1&&P3.flag==1)
{
Line lP2P3=new Line();
t2.mianji(E,P2,P3,lP2P3,t2);
}
double s=t1.S-t2.S;
if(t2.S<s)
System.out.print(Math.round(t2.S*1000000)/(double)1000000+" "+Math.round(s*1000000)/(double)1000000);
else
System.out.print(Math.round(s*1000000)/(double)1000000+" "+Math.round(t2.S*1000000)/(double)1000000);
}
break;
}
case 5:
{
Point D=new Point();
D.x=Double.valueOf(arr[7]);
D.y=Double.valueOf(arr[8]); Line lAD=new Line();
Line lBD=new Line();
Line lCD=new Line(); lAB.L(A,B,lAB);
lAC.L(A,C,lAC);
lAD.L(A,D,lAD);
lBC.L(B,C,lBC);
lBD.L(B,D,lBD);
lCD.L(C,D,lCD); lAD.distanse(A,D,lAD);
lBD.distanse(B,D,lBD);
lCD.distanse(C,D,lCD); Point P1=new Point();
Point P2=new Point();
Point P3=new Point(); triangle t1=new triangle();
triangle t2=new triangle();
triangle t3=new triangle(); if(!lBC.sanjiaox(lBC,lBD,lCD))//判断是BCD否为三角形
{
System.out.print("data error");return;
}
if(A.pointchonghe(A,B)||A.pointchonghe(A,C)||A.pointchonghe(A,D))//A与B/C/D重合
{
System.out.print("on the triangle");return;
}
if(t1.pointwhere(A,B,C,lAB,lAC,lBC)||t1.pointwhere(A,B,D,lAB,lAD,lBD)||t1.pointwhere(A,C,D,lAC,lAD,lCD))
{
System.out.print("on the triangle");return;
} t1.jiaodiannum(A,B,B,C,D,P1,P2,P3,lAB,lBC,lBD,lCD,t1);
t2.jiaodiannum(A,C,B,C,D,P1,P2,P3,lAC,lBC,lBD,lCD,t2);
t3.jiaodiannum(A,D,B,C,D,P1,P2,P3,lAD,lBC,lBD,lCD,t3); if(t1.num==2&&t2.num==2&&t3.num==2)
System.out.print("in the triangle");
else
System.out.print("outof the triangle");
break;
}
default:
{
System.out.print("Wrong Format");
break;
}
}
}
}
虽然使用了面向对象的方法,但是创建类是并没有创建的很完善。
另外,很多内容还是挤在一起,没有去单独构造成函数。
************************************************************************************************************************************************************************************************
(3) 踩坑心得
题目1:
这题有一个点就是过不去,后来发现时由于double类型数据导致的精度问题,这个问题在后面题目中也至关重要。在判断三角形是否为等腰直角三角形时,if(a*a+b*b==c*c)则过不去测试点。需要给其一个误差范围,如if(a*a+b*b-c*c<0.00001),则可通过。(由于这种情况数据不好测试,所以没有附上样例测试)
if(((a*a+b*b-c*c<0.01)||(a*a+c*c-b*b<0.01)||(b*b+c*c-a*a<0.01))//等腰直角三角形
&&((a==b&&a!=c)||(b==c&&b!=a)||(a==c&&a!=b)))
System.out.print("Isosceles right-angled triangle");
*************************************************************************************************************************************************************************************************
题目二:
当使用charAt()找出字符串中的“0”时,找到一个“0”去判断其后面10位数据时,下次使用charAt()找出字符串中的“0”时应该跳跃到这组数据后面的地方开始找零。
如下图,当没有i=i+11语句时,程序运行则出现问题。修改后,则一切ok。
(注释掉i=i+11)
(未注释i=i+11)
*******************************************************************************************************************************************************************************************************
题目3:
String a=new next();//遇到空格换行之类符号结束输入
String a=new nextLine();//本题坐标间用空格分开,所以需用nextLine将空格及其后内容一并输入(输入整行内容)
在去拆分字符串时,我选择分开去拆“ ”和“,”
如果同时去拆空格和逗号,若输入:0 0 ,1,1(即空格与逗号位置调换)程序则不会判出非法输入。
(因为这个改动需要改的地方很多,当时写题的并没有留下截图,所以这个地方无法提供错误展示)
下图为正确输出:
*******************************************************************************************************************************************************************************************************
题目4:
在去算直线表达式时,起初还是用了y=k*x+b,但是这个表达式带来的不便就是斜率不存在的情况需要拎出来特殊讨论,
所以后面又改用a*x+b*y+c=0,真的方便很多。
在选项5中,去判断交叉点是否在两条线段之内(不含四个端点),
即交点O是否在线段AB上或线段CD上。
最先想到的方法是通过四个端点的坐标,去给交点的横纵坐标一个范围
但是发现这种方法会有测试点过不去(没有留截图呜呜呜~~)
后来又改成用距离来判断,如:if((AO+BO==AB)||(CO+DO==CD))
但是发现还是不行。
如下图:
输入5:3,0 0,3 3,0 1.2,1.2
正确输出:3.0,0 false
运行结果与答案不符
3.0变成了2.99999···
因此也就想到了double型的误差问题,在计算出来的交点坐标是有误差的
所以将判断条件改成:if((AO+BO-AB<0.000001)||(CO+DO-CD<0.000001))即可
*****************************************************************************************************************************************************************************************************
题目5:
下图为三角形类中求原本余弦函数:
public void cos(Line l1,Line l2,Line l3,triangle t)//cos
{
double cosA=(Math.pow(l1.D,2)+Math.pow(l2.D,2)-Math.pow(l3.D,2))/(2*l2.D*l1.D);
double cosB=(Math.pow(l3.D,2)+Math.pow(l1.D,2)-Math.pow(l2.D,2))/(2*l3.D*l1.D);
double cosC=(Math.pow(l3.D,2)+Math.pow(l2.D,2)-Math.pow(l1.D,2))/(2*l3.D*l2.D);
}
输出与样例结果不符,后来发现是在算COS时double型数值使得在零附件的值左右浮动不稳定,因而产生误差。
所以判断出来的结果与样例结果不符。
使用Double.parseDouble()来消除误差。
public void cos(Line l1,Line l2,Line l3,triangle t)//cos
{
double cosA=(Math.pow(l1.D,2)+Math.pow(l2.D,2)-Math.pow(l3.D,2))/(2*l2.D*l1.D);
double cosB=(Math.pow(l3.D,2)+Math.pow(l1.D,2)-Math.pow(l2.D,2))/(2*l3.D*l1.D);
double cosC=(Math.pow(l3.D,2)+Math.pow(l2.D,2)-Math.pow(l1.D,2))/(2*l3.D*l2.D); DecimalFormat format=new DecimalFormat("#.00000000000000");
String str1=format.format(cosA);
t.cosA=Double.parseDouble(str1);
String str2=format.format(cosB);
t.cosB=Double.parseDouble(str2);
String str3=format.format(cosC);
t.cosC=Double.parseDouble(str3);
}
注意:输出的数据若小数点后超过6位,只保留小数点后6位,多余部分采用四舍五入规则进到最低位。小数点后若不足6位,按原始位数显示,不必补齐。例如:1/3的结果按格式输出为 0.333333,1.0按格式输出为1.0
一开始是想用%6f来保留6位小数,但是不足六位的也会补齐。
所以后来想到可以用Math.round(X*1000000)/(double)1000000来解决这个问题
在完成选项5:判断点与三角形位置关系时,结果总是不对。
想到前面很多问题都是因为double型数据产生的误差,所以去改了求交点的函数
在求交点时就将误差消除掉
public void jiaodian(Line l1,Line l2,Point O)//两条直线交点
{
O.x=(l1.b*l2.c-l2.b*l1.c)/(l1.a*l2.b-l2.a*l1.b);
O.y=(l2.a*l1.c-l1.a*l2.c)/(l1.a*l2.b-l2.a*l1.b);
O.x=Math.round(O.x*1000000000)/(double)1000000000;
O.y=Math.round(O.y*1000000000)/(double)1000000000;
}
(4) 改进建议(对相应题目的编码改进给出自己的见解,做到可持续改进)
第一次:第一次作业题目是9题,但难度都不大,并且相似度很高,都大差不差,其实可以多加一些其他元素比如数组啊啥的之类的,这样可以更快速的去了解java的相关语法。
第二次:三个题,难度依旧不高,是对字符串数据的处理和分析
第三次:这个跨度太高了,前面两次平平无奇,到第三次刷的一下难度太高了真的好难,而且我们对类和对象的了解和使用并不熟练,出题可不可以平缓一点呜呜,太难了。
而且遇到的很多问题都是由double类型的精度引起的,很多时候都考虑不到这些,所以总会被一些测试点卡住。
每次都要花费很多很多时间去一点一点扣错,真的真的要奔溃了!
真的很希望题目中可以给出这样的一点提示。
(5) 总结
类和对象是刚刚接触到的东西,所以在创建类的时候,很多地方都不完善。
比如Line类中应该去创建两个Point对象,在三角形类中应该创建三个Line类,这样调用方法传参是就会方便很多。
而我在最开始创建的时候并没有想清楚这些东西,导致后续传参时括号里要写很多东西。整体代码都很混乱。
其次是方法的建立,最初并没有建构好,方法到底应该写在哪一个类中,也不是很清晰。
这些在最开始都没有去构思好,导致这个代码很繁琐,参数又多又乱,调理全无。
在编写的过程中,一点点意识到这些问题,但是已经写了很多了再去重头改又很费时间。
所以在以后编写前真的已经去构思好整体框架,去捋清楚整体。
不过哪怕目前写的答案构建的类并没有很完整连贯,但对于类和对象的基本用法真的有了很大的学习和见解,对面向对象的理解也多了几分,同时直观的感受到比起面向过程,面向对象所带来的便捷。对于很多在编写过程中遇到的问题都能够通过自我学习,去掌握到新的函数方法。真的很不错!!!
Blog1:nchu-software-oop-2022-1~3的更多相关文章
- JavaScript--我发现,原来你是这样的JS:面向对象编程OOP[2]--(创建你的那个对象吧)
一.介绍 我们继续面向对象吧,这次是面向对象编程的第二篇,主要是讲创建对象的模式,希望大家能从博客中学到东西. 时间过得很快,还是不断的学习吧,为了自己的目标. 二.创建对象 1.前面的创建对象方式 ...
- JS--我发现,原来你是这样的JS:面向对象编程OOP[3]--(JS继承)
一.面向对象编程(继承) 这篇博客是面向对象编程的第三篇,JS继承.继承顾名思义,就是获取父辈的各种"财产"(属性和方法). 怎么实现继承? 我们的JavaScript比较特别了, ...
- JS--我发现,原来你是这样的JS:面向对象编程OOP[2]--(创建你的那个对象吧)
一.介绍 我们继续面向对象吧,这次是面向对象编程的第二篇,主要是讲创建对象的模式,希望大家能从博客中学到东西. 时间过得很快,还是不断的学习吧,为了自己的目标. 二.创建对象 1.前面的创建对象方式 ...
- JavaScript--我发现,原来你是这样的JS:面向对象编程OOP[1]--(理解对象和对象属性类型)
一.介绍 老铁们,这次是JS的面向对象的编程OOP(虽然我没有对象,心累啊,但是可以自己创建啊,哈哈). JS高程里第六章的内容,这章内容在我看来是JS中很难理解的一部分.所以分成三篇博客来逐个理清. ...
- JS--我发现,原来你是这样的JS:面向对象编程OOP[1]--(理解对象和对象属性类型)
一.介绍 老铁们,这次是JS的面向对象的编程OOP(虽然我没有对象,心累啊,但是可以自己创建啊,哈哈). JS高程里第六章的内容,这章内容在我看来是JS中很难理解的一部分.所以分成三篇博客来逐个理清. ...
- 转:怎样理解OOP?OOP又是什么?
本文转载至:https://blog.csdn.net/q34323201/article/details/80198271. OOP面向对象编程.OOP思想中很重要的有五点,类,对象,还有面向对象的 ...
- 深入C++06:深入掌握OOP最强大的机制
深入掌握OOP最强大的机制 1. 继承的基本意义 类与类之间的关系:①组合:a part of ... 一部分的关系:②继承: a kind of ... 属于同一种的关系: 继承的本质:a. 代码的 ...
- Android游戏引擎总汇 原文出处:http://software.intel.com/en-us/blogs/2012/03/13/game-engines-for-android?page=1
随着Android系统的使用越来越广泛,了解一下Android平台下的游戏引擎就非常有必要.而同时因为基于Intel x86的移动设备越来越多,我也非常关注支持x86的移动游戏引擎.然而就目前为止游戏 ...
- 使用webdriver出现的问题:[18796:1808:0730/131103.313:ERROR:install_util.cc(600)] Failed to read HKLM\SOFTWARE\Policies\Google\Chrome\MachineLevelUserCloudPolicyEnrollmentToken: 系统找不到指定的文件。 (0x2) DevTools lis
1.注册表导致 [5956:4996:0710/155156.898:ERROR:install_util.cc(589)] Unable to create registry key HKLM\SO ...
随机推荐
- Spring源码 06 IOC refresh方法1
参考源 https://www.bilibili.com/video/BV1tR4y1F75R?spm_id_from=333.337.search-card.all.click https://ww ...
- Linux安装JDK并配置环境变量
Linux - 安装jdk并配置环境变量 1. 前往JDK官网, 地址:https://www.oracle.com/java/technologies/downloads/ 复制下载链接 2. ...
- MapReduce核心原理(下)
MapReduce 中的排序 MapTask 和 ReduceTask 都会对数据按key进行排序.该操作是 Hadoop 的默认行为,任何应用程序不管需不需要都会被排序.默认排序是字典顺序排序,排序 ...
- 上传代码到GitHub仓库
上传代码到GitHub仓库 准备工作 意思是自从 21 年 8 月 13 后不再支持用户名密码的方式验证了,需要创建个人访问令牌(personal access token). 这里就不多说了 Git ...
- 简单html js css 轮播图片,不用jquery
这个是自己修改的轮播图片,在网上有的是flash 实现的轮播图片,对搜索引擎不友好, 比如:dedecms 的首页的轮播图是用flash实现滚动的. 所以这个自己修改了一下,实现html+js+css ...
- LGV 引理——二维DAG上 n 点对不相交路径方案数
文章目录 引入 简介 定义 引理 证明 例题 释疑 扩展 引入 有这样一个问题: 甲和乙在一张网格图上,初始位置 ( x 1 , y 1 ) , ( x 2 , y 2 ) (x_1,y_1),(x_ ...
- SpringBoot中maven项目Plugins里resources报红
错误原因:刚开始下载依赖时下载错误导致的 参考:解决idea中maven plugins标红的问题 - 走看看 (zoukankan.com) 如果还不行: 就根据上面提示的地址找到maven的配置包 ...
- XXL-JOB最佳实践与升级指南
前言: xxl-job是国内一款使用者比较多的分布式任务调度平台,我们内部从19年开始使用该款开源软件,使用的是2.0.1版本,并在此基础上做了二次开发,添加了一些定制化的功能.随着使用该定时器的业务 ...
- gem5使用记录,gem5入门学习和环境配置。
工作需要,对gem5有点兴趣,准备自己研究一下,gem5新手刚开始入门学习,主要参考了网上其他前人的文章和官方说明. 目前网上的前人文章有部分有点太早了,稍显过时,我结合自己的经历来整理一下流程. g ...
- 【2022-09-09】Django框架(九)
Django框架(九) cookie与session简介 网址的发展史: 1.起初网站都没有保存用户功能的需求,所有用户访问返回的结果都是一样的. 比如:新闻网页,博客网页,小说... (这些网页是不 ...