Java的第一次博客作业

1.前言
题目集1:此次题目集题量虽多,但较为简单。
知识点为: (1)几种数据类型的定义与使用,如整型,浮点型,字符型,字符串型,数组型等;
(2)字符串的几种方法,如str.charAt()等;
(3)循环语句和判断语句的相结合,如for循环内if语句的判断;
(4)当数据类型的强制转化,如整型强制转化为浮点型c = (float)(0.1*b);//其中b为整型,c为浮点型;
(5)排序方法的使用,如题目7-7我用的冒泡排序法;

题目集2:此次题目集题量适中,有几道还是挺难的。
知识点为: (1)字符串的各种相关方法,如字符串的长度,str.length()
(2)函数的定义、调用、参数等
(3)排序方法的使用,如题目7-2我用的冒泡排序法
(4)闰年的判断,如后三道题都要用的isLeapYear()方法

题目集3:此次题目的最后一道题难度相当相当大,题量虽少,但最后一道题实在是太太难了。
知识点为: (1)类的定义,用类制造对象,在主类中调用其他的类
(2)类的封装性,如7-2的getNextDate()
(3)类里面元素的属性的get和set
(4)正则表达式的使用,如:7-3中对函数表达式的提取,存入,判断等
(5)对大数的处理,如:BigInteger
(6)ArrayList存储数据的使用以及调用list中的元素,如:list.add(m.group())、list.get(i)

2.设计与分析
以下为对三个题目集中的几个题目的源码的设计分析

(1)题目集1的7-8:这道题目考查对三角形各种类型的了解并对其分组分类,让不同种三角形通过不同的算法具有一定的联系,如图1(各种三角形从属关系)

,我做这道题目是思路是首先判断输入是否合法,在判断输入三条边的数据是否能构成三角形,若能构成三角形是普通三角形还是特殊三角形,再由几个if语句来判断是哪种特殊三角形,最后总的代码写出来了,自认为逻辑算法并没有问题,但是一个测试点一直无法通过,经查阅资料和询问同学,浮点型的的平方计算是有误差的,在判断是否为直角三角形的语句中没有考虑到这点卡壳了挺久,最终将if(a*a + b*b == c*c || a*a + c*c == b*b ||c*c + b*b == a*a)改为if(Math.abs(a*a + b*b - c*c) < 0.00001 || Math.abs(a*a + c*c - b*b) < 0.00001|| Math.abs(b*b + c*c - a*a) < 0.00001)通过了改题目的测试点。类图如下
复杂度图如下

(2)题目集2的7-4:输入年月日的值(均为整型数),输出该日期的下一天。 其中:年份的合法取值范围为[1820,2020] ,月份合法取值范围为[1,12] ,日期合法取值范围为[1,31] 。这道题难度适中需要仔细考虑的是月末的下一天,年末的下一天。类图如下
复杂度图如下

isLeapYear()方法来判断输入年份是否为闰年,返回boolean类型,用了一个if语句就可达到目的,该方法代码如下:
public static boolean isLeapYear(int year) { if(year%400 == 0||(year%4 == 0 && year%100 != 0)) return true; else return false; }
checkInputValidity()方法判断输入日期是否合法,返回boolean类型,在这个方法中我用数组来存每一个月的最大天数,代码如下:
int[] a = new int[] {0,31,28,31,30,31,30,31,31,30,31,30,31};
然后再调用isLeapYear(year)来判断二月是28天还是29天进行对a[2]的修改,用if语句来比对输入月份和相应的月份最大天数是否相等,以此判断输入日是否合法加上其他两个或语句来判断输入年份和输入月份是否和法,最后返回一个boolean类型,该方法代码如下:
public static boolean checkInputValidity(int year,int month,int day) { int[] a = new int[] {0,31,28,31,30,31,30,31,31,30,31,30,31}; if(isLeapYear(year) ==true) a[2] = 29; if((year >= 1820 && year <= 2020) && (month >= 1 && month <= 12) && (day >= 1 && day <= 31) && (day <= a[month])) return true; else return false; }
nextDate()方法是求输入日期的下一天,并输出这个日期,没有返回值。我依旧是使用数组来存每一个月的最大天数,然后再调用isLeapYear(year)来判断二月是28天还是29天进行对a[2]的修改,如果输入的日不是月末年末正常加day = day + 1 即可,若是月末年末则进行2个if语句判断即可,该方法代码如下:
public static void nextDate(int year,int month,int day) { int[] a = new int[] {0,31,28,31,30,31,30,31,31,30,31,30,31}; if(isLeapYear(year) ==true) a[2] = 29; day = day + 1; if(day > a[month]) { month = month + 1; day = 1; if(month > 12) { year = year + 1; month = 1; } } System.out.print("Next date is:" + year + "-" + month + "-" + day); }

(3)题目集2的7-5:
类图
复杂度图
在做这道题的时候,我发现这道题和上一道题十分相似,只需将代码稍作修改即可完成要求。我将上一题的求下一天方法代码修改了一下就变为求输入日期的前n天或后n天,该方法代码如下(方法名忘记修改..):

  `public static void nextDate(int n,int year,int month,int day) {
	int[] a = new int[] {0,31,28,31,30,31,30,31,31,30,31,30,31};
	if(isLeapYear(year) ==true)
		a[2] = 29;
	
	if(n < 0) {
		for(int i = 1;i <= -n ;i++) {
			day = day + 1;
			if(day > a[month]) {
				month = month + 1;
				day =  1; 
				if(month > 12) {
					year = year + 1;
					month = 1;
					day = 1;
				}
			}			
		}
	}
	else if(n > 0) {
		for(int i = 1;i <= n ;i++ ) {
			day = day - 1;
			if(day <= 0) {
				month = month - 1;
				day = a[month];
				if(month <= 0) {
					year = year - 1;
					month = 12;
					day = 31;
				}
			}
		}
	}
	
	System.out.print(n + " days ago is:" + year + "-" + month + "-" + day);		
}`

(4)题目集3的7-2:这道题与上面题目题目集2的7-4功能差不多,但是要定义类,用面向对象的思想去解决的这个问题,所以我觉得这道题算法并无很大不同只是代码的语法有所改变。

类图如下

复杂图如下

(5)题目集3的7-3:本题难度巨大无比,思路很差,导致我也只有主类。我首先采用正则表达式对输入的函数表达式进行去空格处理代码如下String input = in.nextLine(); String newinput = input.replace(" ", "");,再进行判断是否非法,若合法则采用正则表达式匹配输入的函数表达式合法的每项都存入list当中,然后再调用qiudao()函数对每项求导,该函数的参数为字符串,在qiudao()函数中将传入参数进行判断,分有各种表达式的种类,再进行求导处理然后输出导函数。
有几个细节需要注意
(1)对大数的处理,我选择的是写一个方法传入字符串返回一个BigInteger类型代码如下:
public static BigInteger A(String str) { BigInteger a = new BigInteger(str); return a; }
(2)输出正数前面的“+”(第一项的不用输出用了一个if语句),代码如下:
public static void f(BigInteger a) { BigInteger b = new BigInteger("0"); if(a.compareTo(b) > 0 ) System.out.print("+"); }
类图如下

复杂度图如下

3.踩坑心得
(1)浮点型平方运算造成误差没有考虑到,卡了很久,如:题目集7-8的判断是否为直角三角形的部分代码“if(aa + bb == cc || aa + cc == bb || cc + bb == aa)”改为“if(Math.abs(aa + bb - cc) < 0.00001 || Math.abs(aa + cc - bb) < 0.00001|| Math.abs(bb + cc - aa) < 0.00001)”;
(2)if-else语句使用的时候花括号的使用不规范造成输出与预期不达标且不报错,要反复检查才可发现;
(3)输出格式的有时候会漏一个空格导致测试点无法通过;
(4)判断语句中的“==”写成“=”导致报错;
(5)switch-case语句使用的时没有用break导致运行结果出bug;
(6)正则表达式中()的优先级问题没有很细的思考,如题目集3的7-3提取表达式中的合法项部分代码:String pattern = "([+-]?[0-9]{1,100}[])?x?";应该为String pattern = "[+-]?([0-9]{1,100}[])?x?";
(7)求导题目中提取表达式的时候正负号问题考虑不周全,如题目集的7-3判断提取项为哪种情况的部分代码
Pattern p1 = Pattern.compile("[+]?[x][''][+-]?[0-9]{1,100}");//x-3类
Matcher m1 = p1.matcher(content);
这样会将 -x^-3类也会进入这个情况中实际上不属于这类情况;
(8)再写代码中一连串的if-else语句,后因算法问题再加入一个if语句但是原先第一个if语句前面没加else,导致改了3小时bug仍无法改好,如题目集3的7-3的部分代码如下
`if(m5.matches()) { //-x^-3
a = new BigInteger(numList.get(0));
b = a.add(a1);

    	if(i > 0)
    	{f(a.multiply(a1));}
    	if(b.compareTo(c) == 0) {
    		System.out.print(a);
    	}
    	else   	System.out.print(a.multiply(a1) + "*x^" + b);
    }
    
     if(m1.matches()) {  //x^-3类
    	a = new BigInteger(numList.get(0));        	
    	b = a.add(a1);
    
    	if(i > 0)
    	{f(a);}
    	if(b.compareTo(c) == 0) {
    		System.out.print(a);
    	}
    	else   	System.out.print( a + "*x^" + b);
    }
      
    else if(m2.matches()) { //4*x类
    	a = new BigInteger(numList.get(0)); 
    	
    	System.out.print(a);
    }
        
    else if(m3.matches()) { //-x类      	
    	System.out.print(-1);
    }
    
    else if(m4.matches()) { //x类      	
    	System.out.print(1);
    }
    
    else  { //a*x^b类
    	a= new BigInteger(numList.get(0));
    	b = new BigInteger(numList.get(1));
    	 
    	 if(i > 0)
     	{f(a.multiply(b));}
    	 if(b.compareTo(c) == 0) {
     		System.out.print(a);
     	}
     	else   	 System.out.print(a.multiply(b) + "*x^" + b.add(a1));
    }`

其中“if(m5.matches()) { //-x^-3类”为后加的但是“if(m1.matches()) { //x^-3类”前面却没加else

4.改进建议
(1)题目集3的7-3中if-else语句写的过多了,正则表达式的使用还不够熟练,没有把多种情况归纳到一起。在写代码的时候也是根据测试点一步一步修改效率极低,应该在写代码之前就多思考,归纳出尽可能多的情况。要多使用类,尽量往面向对象的方向写代码,需要重新构建算法的框架,一定要在下次题目集中写出来。

5.总结
(1)学到的
①类的定义虽然不是很会用,大致知道用但是不会将需求中的条件构建成类;
②对于日期方法的使用;
③稍微学到一一点点正则表达式的使用;
④BigInteger的定义和相关方法的使用;
⑤List存和取数据;
⑥字符串的操作;
⑦循环和判断的各种结合;
(2)期望老师
有些需要自学的东西,希望老师能够稍微讲一点点,让我有个去CSDN的方法;
(3)关于面向对象,感觉还是云里雾里,虽然老师讲了很多面向对象的好处,我也知道但是还是不知道有多好,在大多数情况下我仍然还是选择写一个方法而不是类。
(4)做题目一定不能怕难,题目集3过程是十分艰辛的,前两道我实际话费时间不到5个小时就写完了,随后一直在看第三题,着实没有半点思绪,不敢动手,反反复复去看去学去找资料,但是一点效率都没有(或许我只是想借着自己去学了来避“难”),因为我只是去看去学了,并没有去实现到代码中,这也导致了我八天都没有提交过pta,实在是编译都过不了,最后能写出来也是因为和同学讨论了一下,一语惊醒梦中人,我立刻有了思路,虽然最后遗憾没能得到满分,这也是因为我投入了太多的时间和精力到错误的学习方法之中,在之后的学习一定要边学边实践,不管怎样都要坚持下去,不能因为题目难,就逃避,一定要迎难而上。

posted @ 2021-04-04 22:08  安义Uzi  阅读(45)  评论(0)    收藏  举报