您的位置:首页 > 编程语言

超简单的通过年月得到当月天数,从简单的小例子来解析代码的优化

2015-04-29 23:48 323 查看
首先分析问题,通过年月得到当前月份的天数,按照生活中的惯性,就是分析年份,后分析月份,这里我要说不,虽然这样同样可以算出结果,速度上也与先判断月份相差毫微,虽然这个时间短的可以忽略不计,但是作为一个有情怀的程序员,对代码的要求就是要短小精悍,能省就省,我先列出两种分析方式的算法代码,当然这种写法是最笨重的,这里主要是为了突出问题,优化一步步来,我始终强调,先分析问题,只要会写代码的程序员写完立马就会改为方式二的写法,因为在代码量上很直观,一眼就能看的清楚:

先判断年份的写法:

public static int getCurrentMonthDays1(int year,int month){

        if (year%4==0){
            switch (month){
                case 1:
                    return 31;
                case 2:
                    return 29;
                case 3:
                    return 31;
                case 4:
                    return 30;
                case 5:
                    return 31;
                case 6:
                    return 30;
                case 7:
                    return 31;
                case 8:
                    return 31;
                case 9:
                    return 30;
                case 10:
                    return 31;
                case 11:
                    return 30;
                case 12:
                    return 31;
                default:
                    return 0;
            }
        }else {
            switch (month){
                case 1:
                    return 31;
                case 2:
                    return 28;
                case 3:
                    return 31;
                case 4:
                    return 30;
                case 5:
                    return 31;
                case 6:
                    return 30;
                case 7:
                    return 31;
                case 8:
                    return 31;
                case 9:
                    return 30;
                case 10:
                    return 31;
                case 11:
                    return 30;
                case 12:
                    return 31;
                default:
                    return 0;
            }
        }

    }

先判断月份的写法:

public static int getCurrentMonthDays2(int year, int month) {
        switch (month) {
            case 1:
                return 31;
            case 2:
                if (year%4==0){
                    return 29;
                }else {
                    return 28;
                }
            case 3:
                return 31;
            case 4:
                return 30;
            case 5:
                return 31;
            case 6:
                return 30;
            case 7:
                return 31;
            case 8:
                return 31;
            case 9:
                return 30;
            case 10:
                return 31;
            case 11:
                return 30;
            case 12:
                return 31;
            default:
                return 0;
        }
    }
明显,代码的量上面有很大变化,性能上呢,方法一就不如方法二了,在判断2月份的天数的时候i,两个方法的耗时是一样的,因为都经过了两次判断,但是,如果判断其它月份,方法一就不如方法二了,每次都会多判断一个year%4==0,因为平年和闰年除了2月份不一样,其它月份都一致,所以得到其它月份的天数的时候,还要判断年份就等于脱裤子放屁,多此一举,话糙理不糙,到这里,其实还只是开始,我们来分析代码中的共同点,就是1、3、5、7、8、10、12月都是31天,4、6、9、11月都是30天,这样又有共同点,我们可以简化一下代码了,这次只是代码减少了,速度上与方法2也没有什么差距

方法3:

public static int getCurrentMonthDays3(int year, int month) {
        if (month == 1 ||month == 3 ||month == 5 ||month == 7 ||month == 8 ||month == 10 ||month == 12 ){
            return 31;
        }else if (month==2){
            return year%4==0?29:28;
        }
        return 30;
    }
这样以来,瞬间清爽了好多,不过还不够,我们还要再优化,很明显看到天数为31天的月份有7个,30天的有4个,2月份有一个,计算问题,先易后难,道理很浅显,我们判断2月份的天数经过两个判断就可以ok,判断是否是大月,要经过最少1个判断,最多7个判断才能知道,同理,判断小月最少1个,最多4个判断,综合考虑,判断二月份的条件放在最前面,判断是否是小月放在中间,最后的大月就不用判断了,也就是三个大的范围条件换一下位置,性能会有提升:

方法4:

public static int getCurrentMonthDays4(int year, int month) {
        if (month == 2) {
            return year%4==0?29:28;
        } else if (month == 4 || month == 6 || month == 9 || month == 11) {
            return 30;
        }
        return 31;
    }
说了这里,会陷入一种空口说大话的尴尬境地,你说快就快,你说性能高就高?拿出凭据来,好吧,服不服,不服来跑个分

public static void main(String[] args) {
        long a = System.nanoTime();
        for (int j=0;j<=Integer.MAX_VALUE/2;j++){
            for (int i = 1; i < 13; i++) {
                getCurrentMonthDays4(2016, i);//测试方法3的时候对应换成方法3
            }
            for (int i = 1; i < 13; i++) {
                getCurrentMonthDays4(2015, i);//测试方法3的时候对应换成方法3
            }
        }
        System.out.println(System.nanoTime()-a);
    }
通过这种虐CPU的方式来得到多次测试的时间,本来用的j<=Integer.MAX_VALUE的条件,奈何我的电脑CPU不够强劲,减去一半,平年闰年都弄进去多次运行,最终,方法3的纳秒数在5518968到7031239之间徘徊,方法4的纳秒数在4822850和5222850之间徘徊,这个时间会受硬件影响,不过我多次测试,就是大约在这个区间内,如果你们的电脑CPU好点,这个时间会相对短一点
,不过,从这个大致结果,就已经很能说明问题了,大家可以去试试。这个东西确实简单, 所以高手勿笑,献丑了,在家闲的无聊随便写的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐