Blog作业总结01

 一、前言:

此阶段能力有限,以下均为个人想法,共分为作业概况,设计与分析,踩坑心得,改进建议以及作业总结,仅供大家参考。


 二、三次作业概况:

(1)第一次作业

         所含知识点:基本语法;创建数组;运用选择排序;运用Math.Abs函数计算;用相减小于1*10^(-9)来优化精度丢失的问题。

        题量:较少

        难度:较低

(2)第二次作业:

         所含知识点:利用boolean判断是否闰年,日期是否合法;考虑闰年的不同月份的不同情况。

        题量:中等

        难度:较低

(3)第三次作业:

        所含知识点:涉及到了类的封装性,多个类的写法;运用正则表达式;字符串截取的表达方式;动态数组的使用

       题量:中等

       难度:中等偏高


 

第一次题目集:7-8:

 1、 设计与分析

(1)设计

        该作业的要求是实现三角形类型的判断。

        首先设计将三角形的三条边分别存入数组中,用一个选择排序进行初次筛选,将最大最小边筛选出来,便于后续程序的书写,减少if语序的复杂度。

for(int j=0;j<2;j++) {
            for(int k=j+1;k<3;k++) {
                if(num[j]>num[k]) {
                    double min=num[j];
                    num[j]=num[k];
                    num[k]=min;
                }
            }
        }

      排完序后首先用if条件根据题目要求排除非法输入,其次利用三角形最基本的两边之和大于第三边的性质,(用判断出来的两个小边与最大边相比较即可,此处便体验到了排序后的便捷与准确)排除不是三角形的条件,接下来将等边等腰和等腰直角归为一类,剩下便是直角和一般三角形。

if(num[0]>=1&&num[0]<=200&&num[1]>=1&&num[1]<=200&&num[2]>=1&&num[2]<=200)
        {
            if((num[0]+num[1])>num[2])
            {
                if(num[0]==num[1]&&num[0]==num[2])
                    System.out.println("Equilateral triangle");//3
                
                 else if(num[0]==num[1]||num[0]==num[1]||num[1]==num[2])
                 {
                    
                if((Math. abs(num[2]*num[2]-num[1]*num[1]-num[0]*num[0]))<0.0000000001)
                        System.out.println("Isosceles right-angled triangle");//4
                else
                    System.out.println("Isosceles triangle");//5
                 }
                 
                else if((Math. abs(num[2]*num[2]-num[1]*num[1]-num[0]*num[0]))<0.0000000001)
                    System.out.println("Right-angled triangle");//6
                else
                    System.out.println("General triangle");//7
                    
            }
            else
                System.out.println("Not a triangle");//2
        }
        else
            System.out.println("Wrong Format");//1
        
        }
    }

(2)分析:

         根据PowerDesigner的类图显示,该题只有一个Main类,代码结构较为简单。

         

 

         使用SourceMonitor对该函数的复杂度进行检测,结果如下:

         SourceMonitor的生成报表:
         

 

 

        Idea插件显示圈复杂度

        

       

        由方法和类不多,但是圈复杂度很高,是因为这题用了多个if else语句,导致复杂度很高,代码状况复杂。

2、踩坑心得:

       这题有两个坑容易入。

       第一是数组的使用和排序:一开始,我一直是采用abc来表示三条边,也没有对abc进行排序,导致有很多情况都会出现误差,无法考虑周全。且一开始的if也全都是分开的,导致复杂度太高,还好后面稍微优化了一点。

       第二个便是double的精度问题:由于Java中的小数计算不是那么准确,会出现精度丢失的问题,导致一开始在判断直角三角形的时候采用相减得0得方法并不可用,无法过测试点。故此采用Math. abs(num[2]*num[2]-num[1]*num[1]-num[0]*num[0]))<0.0000000001的方式进行判断(此处用绝对值保险起见)

3、改进建议:

      为降低复杂度,if-else语句在某些情况可用switch-case结构或数组赋初始值的形式表达,使代码更为简洁,可读性更强。


 

第二次题目集:7-4:

 1、 设计与分析

(1)设计:

           该作业的要求输入年月日的值(均为整型数),输出该日期的下一天

           首先设计非法输入,令boolean checkInputValidity = true;如果输入范围不在题目要求的范围内,在此注意闰年1月,2月,7月,8月和每月的边界情况,返回false,则输出("Wrong Format"),然后关闭程序(此处设定System.exit(0);有利于程序的终止)。

if(checkInputValidity(year,month,day)==false) {
                System.out.println("Wrong Format");
                System.exit(0);
        }
        else
            nextDate(year,month,day);
}

           接下来就是判断是否闰年,这里利用闰年数a,a%4==0&&a%100!=0||a%400==0判断是否成立,为后续的日期数据的判断打下基础。

public static boolean isLeapYear( int a) {//判断year是否为闰年,返回boolean类型;
        boolean isLeapYear = false;
            if(a%4==0&&a%100!=0||a%400==0) {
                isLeapYear = true;
                return isLeapYear;
            }
            else
                 {
                    isLeapYear = false;
                    return isLeapYear;
                }
    }    

         最后就是通过if语序进行严密的逻辑讨论:闰年2月到29号,平年到28号就进入下一月份;跨年12月到31号就结束一年进入下一年,并且月份变为1;再考虑大月和小月的问题。

 

if(isLeapYear(year)==true) {
            if(month==2) {
                if(day==29) {
                    monthplus=month+1;
                    dayplus=1;
                }
                else {
                    monthplus=month;
                    dayplus=day+1;
                }
                    System.out.println("Next date is:"+year+"-"+monthplus+"-"+dayplus);
            }
        }
        if(isLeapYear(year)==false) {
            if(month==2) {
                if(day==28) {
                    monthplus=month+1;
                    dayplus=1;
                    yearplus=year;
                }    
                else {
                    monthplus=month;
                    dayplus=day+1;
                    yearplus=year;
                }
                    System.out.println("Next date is:"+yearplus+"-"+monthplus+"-"+dayplus);
            }
        }
            if(month==12) {
                if(day==31) {
                    monthplus=1;
                    dayplus=1;
                    yearplus=year+1;
                }    
                else {
                    monthplus=month;
                    dayplus=day+1;
                    yearplus=year;
                }
                    System.out.println("Next date is:"+yearplus+"-"+monthplus+"-"+dayplus);
            }
            if(month==1||month==3||month==5||month==7||month==8||month==10) {
                if(day==31) {
                    monthplus=month+1;
                    dayplus=1;
                    }
                else {
                    monthplus=month;
                    dayplus=day+1;
                }
                    System.out.println("Next date is:"+year+"-"+monthplus+"-"+dayplus);
            }
            if(month==4||month==6||month==9||month==11) {
                if(day==30) {
                    monthplus=month+1;
                    dayplus=1;
                }    
                else {
                    monthplus=month;
                    dayplus=day+1;
                }
                    System.out.println("Next date is:"+year+"-"+monthplus+"-"+dayplus);
            }

(2)分析:

          根据PowerDesigner的类图显示,该题只有一个类,但利用了三个方法

          

 

 

 

        使用SourceMonitor对该函数的复杂度进行检测,结果如下:

        SourceMonitor的生成报表:

         

 

 

        此题复杂度较高,代码状况非常复杂,原因还是if语句过多。

2、踩坑心得:

       这题有两个坑容易入,第一是if语句的关闭:一开始,未写System.exit(0),程序总是不能很好的关闭。

      第二个是特殊月份的特殊情况没有想到:(这里pta的测试点起到了很大的作用)。其实此题题目并不难,总之一句话,这道题只要足够细心,一次过还是可以的。经过这题,我对闰年月份的判断熟练了不少。

3、改进建议:

      第一,判断是否闰年没有应该写在最上面,体现逻辑的严密性,这里我将其写在第二块,复盘时觉得代码逻辑显得有点不够严谨。

      第二,其实本题完全没必要写那么多的if和else,如果想到用int[] monthDate = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },并且把能和起来的条件用“||”和“&&”表示在一个if里面会降低很多复杂度,同时也会减少丢失考虑情况的误差(有的时候if-else用多了可能会导致代码长度超多题目设置而无法通过,所以还是在允许的情况下,想一种更为优化简洁的方式吧!)

7-5:

 1、 设计与分析

(1)设计:

            该作业的要求输入年月日的值(均为整型数),同时输入一个取值范围在[-10,10]之间的整型数n,输出该日期的前n天(当n > 0时)、该日期的后n天(当n<0时)。

           此题和上题判断非法输入和是否闰年的方式一样,首先设计非法输入,令boolean checkInputValidity = true;如果输入范围不在题目要求的范围内,在此注意闰年1月,2月,3月初,7月,8月初,9月初和每月的边界,跨年的情况,返回false,则输出("Wrong Format"),然后关闭程序(此处设定System.exit(0);有利于程序的终止)。

if(checkInputValidity(year,month,day,n)==false) {
                System.out.println("Wrong Format");
                System.exit(0);
        }
        else
            lastDate(year,month,day,n);
}

          接下来就是判断是否闰年

public static boolean isLeapYear( int a) {//判断year是否为闰年,返回boolean类型;
        boolean isLeapYear = false;
            if(a%4==0&&a%100!=0||a%400==0) {
                isLeapYear = true;
                return isLeapYear;
            }
            else
                 {
                    isLeapYear = false;
                    return isLeapYear;
                }
    }    

         最后通过if语序进行判断(原谅我此处仍未优化):

 闰年2月到29号,平年到28号,若输入为负就进入下一月份;

当3月初输入正数则回到2月,且日期是从29或28号开始相减;

8月和9月输入正数都是从上一月的31号开始减;

跨年12月到31号输入正数就结束一年进入下一年,并且月份变为1;

再考虑大月和小月的问题。

public static void lastDate(int year,int month,int day,int n) {//求输入日期的下一天
    int dayplus=day-n;
            if(month==2&&isLeapYear(year)==true) {
                if(dayplus>29) {
                    month=month+1;
                    dayplus=dayplus-29;
                }
                else if(dayplus<1) {
                    month=month-1;
                   dayplus=31+dayplus;
                }
                else 
                    month=month;
            
            System.out.println(n+" days ago is:"+year+"-"+month+"-"+dayplus);
            return;
        }
            if(month==2&&isLeapYear(year)==false) {
                if(dayplus>28) {
                    month=month+1;
                    dayplus=dayplus-28;
                }
                else if(dayplus<1) {
                    month=month-1;
                   dayplus=31+dayplus;
                }
                else 
                    month=month;
            
            System.out.println(n+" days ago is:"+year+"-"+month+"-"+dayplus);
            return;
    }
            if(month==3&&isLeapYear(year)==true) {
                if(dayplus<1) {
                    month=month-1;
                   dayplus=29+dayplus;
                }
                else 
                    month=month;
            
            System.out.println(n+" days ago is:"+year+"-"+month+"-"+dayplus);
            return;
        }
            if(month==3&&isLeapYear(year)==false) {
                if(dayplus<1) {
                    month=month-1;
                   dayplus=28+dayplus;
                }
                else 
                    month=month;
            
            System.out.println(n+" days ago is:"+year+"-"+month+"-"+dayplus);
            return;
    }
            if(month==12) {
            
                if(dayplus>31) {
                    month=1;
                    year=year+1;
                    
                     dayplus=dayplus-31;
                }
                else if(dayplus<1) {
                    month=month-1;
                   dayplus=30+dayplus;
                }
                else 
                    month=month;
                System.out.println(n+" days ago is:"+year+"-"+month+"-"+dayplus);
                return;
            }
            if(month==1) {
                if(dayplus<1) {
                    month=12;
                   dayplus=31+dayplus;
                   year=year-1;
                }
                else 
                    month=month;
                System.out.println(n+" days ago is:"+year+"-"+month+"-"+dayplus);
                return;
            }
            if(month==8) {
                if(dayplus>31) {
                    month=month+1;
                     dayplus=dayplus-31;
                }
                else if(dayplus<1) {
                    month=month-1;
                   dayplus=31+dayplus;
                }
                else 
                    month=month;
                System.out.println(n+" days ago is:"+year+"-"+month+"-"+dayplus);
                return;
            }
                if(month==5||month==7||month==10) {
                if(dayplus>31) {
                    month=month+1;
                     dayplus=dayplus-31;
                }
                else if(dayplus<1) {
                    month=month-1;
                   dayplus=30+dayplus;
                }
                else 
                    month=month;
                System.out.println(n+" days ago is:"+year+"-"+month+"-"+dayplus);
                return;
            }
            if(month==4||month==6||month==9||month==11) {
                if(dayplus>30) {
                    month=month+1;
                     dayplus=dayplus-30;
                }
                else if(dayplus<1) {
                    month=month-1;
                   dayplus=31+dayplus;
                }
                else 
                    month=month;
                System.out.println(n+" days ago is:"+year+"-"+month+"-"+dayplus);
                return;
            }

(2)分析:

          根据PowerDesigner的类图显示,该题只有一个类,但利用了三个方法。

 

 

 

        使用SourceMonitor对该函数的复杂度进行检测,结果如下:

       SourceMonitor的生成报表:

 

       

 

 

      此题同上题一样,复杂度高,代码状况非常复杂.

2、踩坑心得:

       这题值得注意的是,当用户输入为负数时,实则是日期前推,输入为正时,则为减;经过了第四题,其他应该就没什么问题了。

3、改进建议:

       同上一题一样,最好改为数组的形式,如果怕if语句中的条件太过复杂,还是可以选择拆开写的虽然复杂度相比较高,但是代码看起来较为易懂。 


 

题目集三:7-2:

1、 设计与分析

(1)设计:

          该作业的要求是定义一个类Date,包含三个私有属性年(year)、月(month)、日(day),均为整型数。

          此题由提供的类图可知,需要我们重新构建一个新的Date类,Date date=new Date(year,month,day);并且对year month day 三个属性进行封装变为私有属性,同时构造有参和无参来进行传输数据,用get和set方法将其进行调用如下:

private int year;
    private int month;
    private int day;
    int [] mon_maxnum= new int[] {0,31,28,31,30,31,30,31,31,30,31,30,31};
    
    
     Date(int year,int month,int day) {
         setYear( year);
         setMonth( month);
         setDay(day);
}
    public void setYear(int year) {
    this.year=year;
    }
    public int getYear() {
        return year;
    }
    public int getMonth() {
        return month;
        
    }
    public void setMonth(int month) {
        this.month=month;
    }
    public int getDay() {
        return day;
        
    }
    public void setDay(int day) {
        this.day=day;
    }

           在搭建好结构后,接下来就是和上面两题差不多的思路,判断闰年,输入是否合法以及特殊月份特殊日期的判断。这里相比上面两道题较为优化的是day的数目直接存入数组中,if中的条件判断较为简单了。

public void getNextDate() {
            int monthplus,dayplus,yearplus;

                if(isLeapYear(year)==true&&month==2) {
                    
                        if(day==mon_maxnum[month]+1) {//day=29;
                            monthplus=month+1;
                            dayplus=1;
                        }
                        else {
                            monthplus=month;
                            dayplus=day+1;
                        }
                            System.out.println("Next day is:"+year+"-"+monthplus+"-"+dayplus);
                    }
                if(isLeapYear(year)==false&&month==2) {
                        if(day==mon_maxnum[month]) {//day=28
                            monthplus=month+1;
                            dayplus=1;
                            //yearplus=year;
                        }    
                        else {
                            monthplus=month;
                            dayplus=day+1;
                            //yearplus=year;
                        }
                            System.out.println("Next day is:"+year+"-"+monthplus+"-"+dayplus);
                    }
                    if(month==12) {
                        if(day==mon_maxnum[month]) {
                            monthplus=1;
                            dayplus=1;
                            yearplus=year+1;
                        }    
                        else {
                            monthplus=month;
                            dayplus=day+1;
                            yearplus=year;
                        }
                            System.out.println("Next day is:"+yearplus+"-"+monthplus+"-"+dayplus);
                    }
                    if(month==1||month==3||month==5||month==7||month==8||month==10) {
                        if(day==mon_maxnum[month]) {
                            monthplus=month+1;
                            dayplus=1;
                            }
                        else {
                            monthplus=month;
                            dayplus=day+1;
                        }
                            System.out.println("Next day is:"+year+"-"+monthplus+"-"+dayplus);
                    }
                    if(month==4||month==6||month==9||month==11) {
                        if(day==30) {
                            monthplus=month+1;
                            dayplus=1;
                        }    
                        else {
                            monthplus=month;
                            dayplus=day+1;
                        }
                            System.out.println("Next day is:"+year+"-"+monthplus+"-"+dayplus);
                    }

    }

(2)分析:

           根据PowerDesigner的类图显示,直观地看出,该题涉及了两个类Date和Main,利用了多个方法:

         

 

 

          使用SourceMonitor对该函数的复杂度进行检测,结果如下:

          SourceMonitor的生成报表:

          

 

 

          此题复杂度较高,代码状况非常复杂。

2、踩坑心得:

        该类题对于一开始接触新增类的小白来说,写代码的路途确实有点坎坷,好在第三次作业第一题有较为明了的提示,代码搭建的过程相比第一次较为顺畅,只不过在此题目的要求下没办法采用if的简单逻辑角度进行判断,而要采用    int [] mon_maxnum= new int[] {0,31,28,31,30,31,30,31,31,30,31,30,31};day==mon_maxnum[month]来计算yearplus、monthplus和dayplus的数据变化。

3、改进建议:

      同样还是在大块的if-else语句中进行优化和修改吧(实话实说,提交的时候,已经好几次提醒超出代码长度了),至于其他的修改及方式,本人还在努力学习当中,我相信通过日后的学习与练习会使代码更加优化简洁的。

 

7-3:

1、 设计与分析

(1)设计:

         该题的要求是编写程序性,实现对简单多项式的导函数进行求解。同时还要满足以下要求

  • 当某一项为“0”时,则该项不需要显示,但如果整个导函数结果为“0”时,则显示为“0”;
  • 当输出结果第一项系数符号为“+”时,不输出“+”;
  • 当指数符号为“+”时,不输出“+”;
  • 当指数值为“0”时,则不需要输出“x^0”,只需要输出其系数即可。

         这道题的想法都包括在心得体会里了,话不多说,直接附代码:

import java.util.ArrayList;
import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
 
public class Main {

    public static void main(String[] args) {
        Array array=new Array();
        array.array();
    }
      
}
    class Array {
        String string;
        int i,j;
        void array() {
        Scanner input = new Scanner(System.in);
        string=input.nextLine();
        String [] str=string.split("");//分割字符串(但不完全保留)
         
        ArrayList<String> num = new ArrayList<>();
        Pattern  p1 = Pattern.compile("([+-]?x\\^)|(\\*x\\^)|(\\*x)|[+-]{1}x|^x[+-]{1}\r\n");
        string=string.replaceAll("\\s*","");
        Matcher  m1 = p1.matcher(string);
           int count=-1;
           while(m1.find()){
               count=count+1;
                num.add(m1.group());
           }
        ArrayList<String> mum = new ArrayList<>();
        Pattern  p2 = Pattern.compile("[+-]?\\d+");
        Matcher  m2 = p2.matcher(string);
        int um=-1;
            while(m2.find()){
                um=um+1;
                 mum.add(m2.group());
                 
            }

            if(string.indexOf("+0*")!=-1||string.indexOf("^0")!=-1||string.indexOf("-0*")!=-1) {
                System.out.println("Wrong Format");
              System.exit(0);
            }
            else if(num.size() == 0 && mum.size() == 1) {
                System.out.println("0");
            }
            else {
                int number1 = 0;
                int number2 = 0;
                for(i=0,j=0;i < num.size();i++,j++) {
                    if(num.get(i).equals("*x^")) {
                        number1=Integer.parseInt(mum.get(j))*Integer.parseInt(mum.get(j+1));
                        number2=Integer.parseInt(mum.get(j+1))-1;
                        if(number1 > 0 && i != 0)
                            System.out.print("+");

                        System.out.print(number1 + "*x^" + number2);
                        j++;
                    }
                    else if(num.get(2).equals("*x")) {
                        number1=Integer.parseInt(mum.get(4));
                        if(number1 > 0 && i != 0)
                            System.out.print("+");
                        System.out.print(number1);
                    }    
                }   
            } 
        }
        
    }

(2)分析:

          根据PowerDesigner的类图显示,直观地看出,该题涉及了两个类Array和Main,其次在Array中利用了多个方法:

       

 

         使用SourceMonitor对该函数的复杂度进行检测,结果如下:

         SourceMonitor的生成报表:

         

        此题复杂度较高,代码状况较为复杂。

2、踩坑心得:

       这道题开头老师就交给我们一个小任务——学习正则表达式,但当我学完之后我却发现,将其内容串通起来好像还是有点复杂的。一开始我用想过用split方法暴力解决,但是却无法切出我想要的数据,后来我用\\*|\\^|\\+|[a-z]|\\d+|-进行切割,数字和字符都能一项一项的切出来,却无法切开负数。经过讨论,发现这样切出一项一项的好像并没有什么用,于是用([+-]?x\\^)|(\\*x\\^)|(\\*x)|[+-]{1}x|^x[+-]{1}\r\n"将其切成一个个的子项进行求导的计算。

       同时,由于课堂上老师提到了一次动态数组,我就在此利用上了,但是因为才学浅薄,还未完全学会动态数组的用法,为后续数据穿插的代码书写造成了一定的困扰和麻烦。

3、改进建议:

      我认为这里对于新手小白来说,存储数据还是用正常的数组会比较好调用(当然,大佬们可跳过这条建议)同时,由于求导的函数表达式有可能出现大数,还是用BigInteger会比较稳妥。


 

三、作业总结:

1、第一次作业虽然题目量较大,但做起来还是挺顺畅,只要会Java的基本格式书写就没什么问题。

2、第二次作业主要是通过严密的逻辑来考虑现实生活中,平年润年对于不同月份日期加减的限制要求,从而选择一个正确且便捷的方式进行加减计算,整体来说,除了要注意复杂度,其他并没有什么太大的问题。

3、第三次作业,别看只有三道题,却困住了许多同学,首先是前两到类的增加以及封装性,但根据题目的提示,再结合书上的知识点,在搭好所要求的框架后,其他问题就迎刃而解了。当然,这里涉及到的新知识点还挺多,对这两道题进行深度学习和理解对于后续的学习还是很有必要的。重点是第三题,首先是正则表达式的书写就让我有点犯难,其次就是选择分割的位置的选取以及动态数组熟练应用的问题。

4、总而言之,经过这三次大作业,我发现自己的知识储备量还远远不够,在后续的学习中,我会与同学多多讨论,查找有关资料对Java及其语法的使用进行更深入的认知与学习,同时,要对书本有更深刻的解读。

                                                                                                                                                                                                                                        

 

                                                                                                                                                                                                                                                                                                                           2021-04-04

 

posted @ 2021-04-04 20:41  张艺兴的小仙女  阅读(117)  评论(1)    收藏  举报