Blog作业01
(1)前言:
1.题目集1中的7-8考察了对于数列有序排列的知识,涉及到了冒泡法排序的运用,题目总体简易,易于设计。
2.题目集2中的7-4主要涉及到了主类中方法的设计以及方法的实现,考察对于月份以及相关日期的协调,对方法的设计提出了相关要求;7-5同7-4一样是对于日期的处理,不过在此基础了提出更高要求,难度有所提升不过总体设计及思路一致。
3.题目集3中的7-2是同样是对于日期的处理,但是对于类的设计提出了要求,要求掌握并运用有个类的构造和使用相关知识。
4.题目集3中的7-3考察了有关正则表达式和类的构造相关知识,总体偏难,对于知识的运用难度较高。
(2)设计与分析:
1.题目集1中的7-8只需一个主函数即可,图解如下:
先接受相关数据并判断是否在范围以内:
Scanner put = new Scanner(System.in);
double n1=put.nextDouble();
double n2=put.nextDouble();
double n3=put.nextDouble();
if(n1<1||n1>200||n2<1||n2>200||n3<1||n3>200) {
System.out.printf("Wrong Format");
}
对于输入的数据根据定理:三角形任意两边之和大于第三条边判断合法性。具体实现使用最小两条边之和与第三条边比较。
x1=n1<n2? n1:n2;
x1=x1<n3? x1:n3;
x3=n1>n2? n1:n2;
x3=x3>n3? x3:n3;
x2=n1+n2+n3-x1-x3;
//这里确定最大的边和其他两边
if(Math.abs(x1-x3)<s&&Math.abs(x1-x2)<s) {
System.out.printf("Equilateral triangle");
}else {
if(Math.abs(x3*x3-x1*x1-x2*x2)<s) {
if(Math.abs(x1-x2)<s) {
System.out.printf("Isosceles right-angled triangle");
}else {
System.out.printf("Right-angled triangle");
}
}else {
if(x1+x2>x3) {
if(Math.abs(x1-x2)<s||Math.abs(x2-x3)<s) {
System.out.printf("Isosceles triangle");
}else {
System.out.printf("General triangle");
}
}
}else {
System.out.printf("Not a triangle");
}
//分别根据不同条件进行初步判断,在根据判断结果深入判断
例如对于等腰直角三角形的判断,先初步判断是否存在两边相同,若存在进一步根据勾股定理判断是否是等腰直角三角形。满足条件即是,否则是等腰三角形。
- 题目集2中的7-4涉及到2个方法处理数据,先展示有关的函数图解:
具体分析第一个函数:
IsLeapYear(int year)函数代码如下:
public static boolean isLeapYear(int year) {
if((year%4==0&&year%100!=0)||year%400==0) {
return true;
}else {
return false;
}
}
//根据闰年的定义判断接收的年份是否为闰年,便于之后涉及到月份的计算进行处理。
主函数代码如下:
public static void main(String[] args) {
Scanner put = new Scanner(System.in);
int year=put.nextInt();
int mon=put.nextInt();
int day=put.nextInt();
int i,j;
int ary[]= {0,31,28,31,30,31,30,31,31,30,31,30,31};
//用一个数组来存对应下标的月份对应的总天数
if(year<1820||year>2020||mon<1||mon>12) {
System.out.print("Wrong Format");
}else {
if(isLeapYear(year)) {
ary[2]=29;
}
if(day<1||day>ary[mon]) {
System.out.print("Wrong Format");
}else {
if(mon==12&&day==ary[mon]) {
year=year+1;
mon=1;
day=1;
}else {
if(day==ary[mon] ){
mon++;
day=1;
}else {
day++;
}
}
System.out.print("Next date is:"+year+"-"+mon+"-"+day);
}
}
}
先判断输入数据的合法性,考察年月日各值是否超过有效范围或小于等于0,同时考察日的值是否超过相应月份总天数或为非负数。
根据不同年份确定2月份总天数,便于之后进一步判断;
对于月份处理总体有两个情况:
第一种情况为月份等于12,这时要考虑日的值是否为该月天数总值。如果满足则后一天日期要考虑年份加一,月份变为一,日的值也为一;否则只是日的值加一。
第二种情况为月份不等于12,这时依然考虑日的值是否为该月天数总值。如果
满足后一天日期月份加一,日的值变为一;否则只是日的值加一。
3.题目集2中的7-5涉及到2个方法处理数据,先展示有关的函数图解:
具体分析第一个函数:
IsLeapYear(int year)函数代码如下:
public static boolean isLeapYear(int year) {
if((year%4==0&&year%100!=0)||year%400==0) {
return true;
}else {
return false;
}
}
//根据闰年的定义判断接收的年份是否为闰年,便于之后涉及到月份的计算进行处理。
主函数代码如下:
public static void main(String[] args) {
Scanner put = new Scanner(System.in);
int year=put.nextInt();
int mon=put.nextInt();
int day=put.nextInt();
int add=put.nextInt();
int i,j;
int ary[]= {0,31,28,31,30,31,30,31,31,30,31,30,31};
//用一个数组来存对应下标的月份对应的总天数
if(year<1820||year>2020||mon<1||mon>12) {
System.out.print("Wrong Format");
}else {
if(isLeapYear(year)) {
ary[2]=29;
}
if(day<1||day>ary[mon]) {
System.out.print("Wrong Format");
}else {
if(add==0) {
System.out.print("0 days ago is:"+year+"-"+mon+"-"+day);
}else {
System.out.print(add+" days ago is:");
if(add<0) {
System.out.print("");
add=add*(-1);
if(day+add>ary[mon]) {
if(mon==12) {
year=1
day=day+add-ary[mon];
mon=1;
}else {
day=day+add-ary[mon];
mon=mon+1;
}
}else {
day=day+add;
}
}else {
if(day-add<0) {
System.out.print("");
if(mon==1) {
year=year-1;
day=day-add+31;
mon=12;
}else {
day=ary[mon-1]+day-add;
mon=mon-1;
}
}else {
day=day-add;
}
}
System.out.print(year+"-"+mon+"-"+day);
}
}
}
}
先判断输入数据的合法性,考察年月日各值是否超过有效范围或小于等于0,同时考察日的值是否超过相应月份总天数或为非负数。
根据不同年份确定2月份总天数,便于之后进一步判断;
根据最后输入的有关日期改变的add值进场考察:
第一种情况:add小于0时,日期往后推:
对于月份处理总体有两个情况:
第一种小情况为月份等于12,这时要考虑日的值加上add绝对值是否超过该月天数总值。如果满足则后几天日期要考虑年份加一,月份变为一,日的值也为相应超过的值;否则只是日的值加上add的绝对值。
第二种小情况为月份不等于12,这时要考虑日的值加上add绝对值是否超过该月天数总值。如果满足则后几天日期要考虑月份加一,日的值也为相应超过的值;否则只是日的值加上add的绝对值。
第二种情况:add大于0时,日期往前推:
对于月份处理总体依然有两个情况:
第一种小情况为月份等于1,这时要考虑日的值减去add绝对值是否小于等于0。如果满足则后几天日期要考虑年份减一,月份变为12,日的值也为12月份天数总值加上日的值减去add绝对值;否则只是12月份天数总值加上日的值减去add绝对值。
第二种小情况为月份不等于1,这时要考虑日的值减去add绝对值是否小于等于0。如果满足则后几天日期要考虑月份减一,日的值也为前一个月份天数总值加上日的值减去add绝对值;否则只是12月份天数总值加上日的值减去add绝对值。
4.题目集3中的7-2涉及到类的设计和多个方法的实现,有关类和函数图解如下:
Data类的设计包含了有关变量的设计和函数的定义。
变量包括了年份,月份,日值。
分别在特殊构造Data(int x,int y,int z)中传入输入的各值对于类内部变量进行了赋值。
类首先定义IsLeapYear(int year)函数。
IsLeapYear(int year)函数代码如下:
public static boolean isLeapYear(int year) {
if((year%4==0&&year%100!=0)||year%400==0) {
return true;
}else {
return false;
}
}
}
//根据闰年的定义判断接收的年份是否为闰年,便于之后涉及到月份的计算进行处理。
Pant()函数代码如下:
public void pant() {
if(year<1900||year>2000||month<1||month>12) {
System.out.print("Date Format is Wrong");
}else {
if(isLeapYear(year)) {
ary[2]=29;
}
if(day<1||day>ary[month]) {
System.out.print("Date Format is Wrong");
}else {
if(month==12&&day==ary[month]) {
year=year+1;
month=1;
day=1;
}else {
if(day==ary[month] ){
month++;
day=1;
}else {
day++;
}
}
System.out.print("Next day is:"+year+"-"+month+"-"+day);
}
}
}
先判断输入数据的合法性,考察年月日各值是否超过有效范围或小于等于0,同时考察日的值是否超过相应月份总天数或为非负数。
根据不同年份确定2月份总天数,便于之后进一步判断;
对于月份处理总体有两个情况:
第一种情况为月份等于12,这时要考虑日的值是否为该月天数总值。如果满足则后一天日期要考虑年份加一,月份变为一,日的值也为一;否则只是日的值加一。
第二种情况为月份不等于12,这时依然考虑日的值是否为该月天数总值。如果
满足后一天日期月份加一,日的值变为一;否则只是日的值加一。
最后打印后一天日期的结果。
5.题目集3中的7-3涉及到类的设计和多个方法的实现,有关类和函数图解如下:
本题求解输入函数的导函数,涉及到了对于输入函数合法性判断(考察了正则表达式的理解和运用),涉及到了类的设计和有关方法的实现。
具体分析如下:
定义一个动态数组list便于存储有效字符串,start接收输入的有效且初步处理后的字符串,head在求导时考察第一项使用(根据第一项的特殊性设立),flag启到在进一步判断中终止循环并协调打印的作用。
本题涉及到函数较为复杂,我们依次分析:
1输入字符串并且删除所有空格得到更为标准的形式:
Scanner in=new Scanner (System.in);
String linput=in.nextLine();
String input =new String (linput.replace(" ",""));
对于标准字符串进行初步判断:
if(Pattern.matches("[0-9]+",input)) {
System.out.print(0);
}else {
deal ans=new deal(input);
ans.print();
}
标准字符串为常数,求导后必然为0;否则根据标准字符串构造类ans,并调用ans在的函数print()。
2定义三个有关正则表达式的字符串:
String totalRegex = "([-+]?([1-9]+[0-9]*(\\*)?)?x?(\\^[+-]?[1-9]+[0-9]*)?)+";
String sbuRegex = "[-+]?([1-9]+[0-9]*(\\*)?)?x?(\\^[+-]?[1-9]+[0-9]*)?";
Stringsecond="[-+]?((([2-9]+[0-9]*)|([1-9]+[0-9]+))(\\*)?)?x?(\\^[+-]?(([2-9]+[0-9]*)|([1-9]+[0-9]+)))?";
判断标准字符串是否满足要求形式:
boolean bl=Pattern.matches(totalRegex, start);
若bl为false时则表达式有误。
System.out.println("Wrong Format");
bl为true时再对于字符串按格式进行分割,格式由字符串sbuRegex确定。
Pattern pattern = Pattern.compile(sbuRegex);
Matcher matcher=pattern.matcher(start);
3将分割后的若干字符串进行进一步判断,代码如下:
while(matcher.find()){
String tmp=matcher.group();
int begin=matcher.start();
int end=matcher.end();
if(Pattern.matches(second, tmp)) {
int i;
for(i=1;i<=5;i++) {
if(Pattern.matches(arr[i], tmp)) {
String arry;
arry=tmp;
if(i==2) {
String k="(\\*)x";
String []just2=arry.split(k);
BigInteger t1 = new BigInteger(just2[0]);
Double k1=t1.doubleValue();
if(k1>0) {
list.add("+"+just2[0]);
}else {
list.add(just2[0]);
}
break;
}
if(i==3) {
String k="(\\*)x(\\^)";
String []just2=arry.split(k);
BigInteger t1 = new BigInteger(just2[0]);
BigInteger t2 = new BigInteger(just2[1]);
Double x=t1.multiply(t2).doubleValue();
String a1;
if(x>0) {
a1="+"+String.valueOf(t1.multiply(t2));
}else {
a1=String.valueOf(t1.multiply(t2));
}
String c;
String b1="";
if(t2.intValue()!=2) {
BigInteger cha=t2.add(new BigInteger("-1"));
b1=String.valueOf(cha);
c=a1+"*x^"+b1;
}else {
c=a1+"*x"+b1;
}
list.add(c);
break;
}
if(i==4) {
String k="x(\\^)"
String []just2=arry.split(k);
BigInteger t1 = new BigInteger(just2[1]);
double k1=t1.doubleValue();
//long b=Long.parseLong(just2[1]);
String a1;
if(k1>0) {
a1="+"+String.valueOf(t1);
}else {
a1=String.valueOf(t1);
}
String b1="";
if(k1!=2) {
BigInteger cha=t1.add(new BigInteger("-1"));
b1="^"+String.valueOf(cha);
}
String c=a1+"*x"+b1;
list.add(c);
break;
}
if(i==5) {
if(tmp.charAt(0)=='-') {
list.add("-1");
}else {
list.add("+1");
}
break;
}
}
}
if(end==start.length()) {
break;
}
if(i==6) {
System.out.println("Wrong Format");
flag=1;
break;
}
}else {
System.out.println("Wrong Format");
flag=1;
break;
}
}
if(flag==0) {
for(int i=0;i<list.size();i++) {
if(i==0&&list.get(0).charAt(0)=='+') {
System.out.print(list.get(0).substring(1));
}else {
System.out.print(list.get(i));
}
}
}
解释以上代码如下:
1先是根据字符串
String second =
"[-+]?((([2-9]+[0-9]*)|([1-9]+[0-9]+))(\\*)?)?x?(\\^[+-]?(([2-9]+[0-9]*)|([1-9]+[0-9]+)))?"
排除以下表达式中系数和指数为1的情况,代码是:
if(Pattern.matches(second, tmp))
2跟踪5个正则表达式字符串判断相应情况:
arr[1]="[+-]?[1-9]+[0-9]+"; //全为数字型
arr[2]="[+-]?[1-9]+[0-9]*(\\*)x"; //数字*x;
arr[3]="[+-]?[1-9]+[0-9]*(\\*)x\\^[+-]?[1-9]+[0-9]*"; //数字*x^数字;
arr[4]="[+-]?x(\\^)[+-]?[1-9]+[0-9]*"; // x^数字
arr[5]="[+-]?x";
有关循环匹配的代码是:
for(i=1;i<=5;i++) {
if(Pattern.matches(arr[i], tmp)) {
String arry;
arry=tmp;
if(i==2) {
String k="(\\*)x";
String []just2=arry.split(k);
BigInteger t1 = new BigInteger(just2[0]);
Double k1=t1.doubleValue();
if(k1>0) {
list.add("+"+just2[0]);
}else {
list.add(just2[0]);
}
break;
}
if(i==3) {
String k="(\\*)x(\\^)";
String []just2=arry.split(k);
BigInteger t1 = new BigInteger(just2[0]);
BigInteger t2 = new BigInteger(just2[1]);
Double x=t1.multiply(t2).doubleValue();
String a1;
if(x>0) {
a1="+"+String.valueOf(t1.multiply(t2));
}else {
a1=String.valueOf(t1.multiply(t2));
}
String c;
String b1="";
if(t2.intValue()!=2) {
BigInteger cha=t2.add(new BigInteger("-1"));
b1=String.valueOf(cha);
c=a1+"*x^"+b1;
}else {
c=a1+"*x"+b1;
}
list.add(c);
break;
}
if(i==4) {
String k="x(\\^)";
String []just2=arry.split(k);
BigInteger t1 = new BigInteger(just2[1]);
double k1=t1.doubleValue();
//long b=Long.parseLong(just2[1]);
String a1;
if(k1>0) {
a1="+"+String.valueOf(t1);
}else {
a1=String.valueOf(t1);
}
String b1="";
if(k1!=2) {
BigInteger cha=t1.add(new BigInteger("-1"));
b1="^"+String.valueOf(cha);
}
String c=a1+"*x"+b1;
list.add(c);
break;
}
if(i==5) {
if(tmp.charAt(0)=='-') {
list.add("-1");
}else {
list.add("+1");
}
break;
}
}
}
满足条件的项总共有5中情况,分别根据不同的情况计算相应导函数,并将结果加入到动态数组list中。若在计算过程中以上5种情形都不配对,即分割的表达式有误,将flag=1赋值后打印Wrong Format。
在之后运用flag令程序不打印数组中元素且终止循环,相关代码如下:
if(flag==0) {
for(int i=0;i<list.size();i++) {
if(i==0&&list.get(0).charAt(0)=='+') {
System.out.print(list.get(0).substring(1));
}else {
System.out.print(list.get(i));
}
}
}
此时若表达式正确则将其按特定的模式分割为若干项,并分别计算各项的求导结果,最后将其依次打印;否则打印Wrong Format。
(3)采坑心得:
本次答题过程总体较为顺利,题目难度较简易,唯一值得注意的是题目集3中的7-3题,求解过程中犯了两个错误。
1使用数据类型取值范围不满足题意要求。
比如当项满足形式数字*x时,现代码处理如下:
String k="(\\*)x";
String []just2=arry.split(k);
BigInteger t1 = new BigInteger(just2[0]);
Double k1=t1.doubleValue();
if(k1>0) {
list.add("+"+just2[0]);
}else {
list.add(just2[0]);
}
原来代码t1定义类型使用long,后再输入示范:
x^-5+6*x^7-1200*x^-1000+54468799958488*x^-925546
输出本是:
-5*x^-6+42*x^6+1200000*x^-1001-50413379926378734448*x^-925547
但是显示结果有误,后分析原因考虑到54468799958488数据超过long型数的范围,尝试改用更大范围的Biglnteger型数,改示范输出正确且PTA通过。
2加入字符串数组的求导后的项形式有误。
考察数字*x^数字形式的项,代码如下:
String k="(\\*)x(\\^)";
String []just2=arry.split(k);
BigInteger t1 = new BigInteger(just2[0]);
BigInteger t2 = new BigInteger(just2[1]);
Double x=t1.multiply(t2).doubleValue();
String a1;
if(x>0) {
a1="+"+String.valueOf(t1.multiply(t2));
}else {
a1=String.valueOf(t1.multiply(t2));
}
String c;
String b1="";
if(t2.intValue()!=2) {
BigInteger cha=t2.add(new BigInteger("-1"));
b1=String.valueOf(cha);
c=a1+"*x^"+b1;
}else {
c=a1+"*x"+b1;
}
list.add(c);
原代码接收到的项处理有误,输出图示如下:
分析原因考虑到了原正则表达式判断字符串(\\*)x^(\\^)对于正则表达式判断有误,改用(\\*)x(\\^)判断正确,显示结果如下:
(4)改进建议:本次代码对于类的理解与设计还是停留在主函数直接接收并处理数据,对于方法的理解过于简单直接。设计类时往往要考虑到不同方法分工明确,各有作用,应当避免一个方法对于数据过多处理,兼顾了其他方法的分工。
在今后的学习过程中应该提高对于类的理解,提升设计类的能力,降低类中方法的耦合性。
(5)总结:学习到了正则表达式的实际运用,掌握到了几个与正则表达式有关的函数。Pattern.compile()函数接收字符串赋值给Pattern类型的模式变量(以pattern为例)。pattern.matcher()接收函数将其根据模式分割为若干个字符串,在之后使用函数matcher.find()逐个使用字符串。同时Pattern.matches(String ,String )接收两个字符串判断字符串是否满足正则表达式,其返回值为boolean型。罗老师在实验课中教导我们实验Debug来设置断点以便分析代码错误部分的方法提供了帮助,今后在学校过程中应该多多分析,认真掌握老师指导的方法,平时多多写代码提升能力。
浙公网安备 33010602011771号