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

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

先判断年份的写法:

    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好点,这个时间会相对短一点
,不过,从这个大致结果,就已经很能说明问题了,大家可以去试试。这个东西确实简单, 所以高手勿笑,献丑了,在家闲的无聊随便写的。

时间: 2024-10-01 22:52:20

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

SQL 获取当月天数的方法

之前网上找到的方法是 select day(dateadd(mm,1,getdate())-day(getdate())) 该方法平时能工作正常,但是在某些月份31号时会发生错误,比如1月31号,8月31号等 重新自己改了下方法,能正常获取到当月天数 select day(dateadd(MONTH,1,GETDATE()-DAY(GETDATE())+1)-1) 可用以下语句进行测试对比 declare @date datetime=convert(datetime,'2014-01-31')

获取当月天数

今天写个日历,需要知道当月天数,在百度N久之后,都没有收获或者方法不尽人意, 于是,我看NSCanlendar类中的方法说明,终于找到了rangeIfUnit这个方法,帮助说明如下图所示, ① 小单位是NSDayCalendarUnit,大单位是NSYearCalendarUnit,并不是要取这一年包含多少天,而是要取"天"(Day)这个单位在这一年(Year)的取值范围.其实不管你提供的日期是多少,返回的值都是"1--31". ② 小单位是NSDayCalenda

使用SQL语句查询日期(当月天数,当月第一天,当月最后一天,本年最后一天,当月第一个星期) 日期转字符串

取某月天数:select day(dateadd(month,1,'2012-02-01')-1) --当月天数 select day(dateadd(ms,-3,DATEADD(m, DATEDIFF(m,0,getdate())+1,0))) ---当月第一天 select dateadd(d,-day(getdate())+1,getdate()) ---当月最后一天 select dateadd(d,-1,dateadd(m,1,dateadd(d,-day(getdate())+1,g

用C#Winform写个简单的批量清空文件内容和删除文件的小工具

用C#Winform写个简单的批量清空文件内容和删除文件的小工具 本文介绍这个简单得不能再简单的小项目.做这个项目,有以下目的. 1 当然是做个能用的工具 2 学习使用Github 关于用VS2013创建一个项目并添加到Github的教程,请参考(http://www.admin10000.com/document/4004.html).简单来说,就是先用VS创建项目:然后在Github网站上创建一个Respo(本项目的代码托管项目),记下(https://*.git)那个地址:最后用"提交&q

Spring简单的小例子SpringDemo,用于初略理解什么是Spring以及JavaBean的一些概念

一.开发前的准备 两个开发包spring-framework-3.1.1.RELEASE-with-docs.zip和commons-logging-1.2-bin.zip,将它们解压,然后把Spring开发包下dist目录的所有包和commons-logging包下的commons-logging-1.1.1.jar复制到名为Spring3.1.1的文件夹下.那么Spring开发所需要的包就组织好了. 二.建立项目,导入包 在项目节点上右键,Build Path/ADD Libraries/U

BAT&amp;nbsp;批处理脚本教程(如果可以用电脑让事情变的更简单,何不让它变得更简单呢!)

第一章 批处理基础 第一节 常用批处理内部命令简介批处理定义:顾名思义,批处理文件是将一系列命令按一定的顺序集合为一个可执行的文本文件,其扩展名为BAT或者CMD.这些命令统称批处理命令. 小知识:可以在键盘上按下Ctrl+C组合键来强行终止一个批处理的执行过程. 了解了大概意思后,我们正式开始学习.先看一个简单的例子! @echo off echo "欢迎来到非常BAT!" pause 把上面的3条命令保存为文件test.bat或者test.cmd然后执行, 他就会在屏幕上显示以下二

ASP.NET Cookie对象到底是毛啊?(简单小例子)

记得刚接触asp.net的时候,就被几个概念搞的头痛不已,比如Request,Response,Session和Cookie.然后还各种在搜索引擎搜,各种问同事的,但是结果就是自己还是很懵的节奏. 那cookie到底是毛啊?下面是我最不喜欢的一种解释方式(官方定义吧应该叫,我这种智商根本读不懂嘛~) Cookie对象也称缓存对象,该对象用于保存客户端浏览器请求的服务器页面,也可用它存放非敏感性的用户信息. 以前根本读不懂啊,现在其实也懵懵的. 还是用例子能把这个概念搞明白 1.做一个用户登录的界

完成一段简单的Python程序,用于实现一个简单的加减乘除计算器功能

#!/bin/usr/env python#coding=utf-8'''完成一段简单的Python程序,用于实现一个简单的加减乘除计算器功能'''try: a=int(raw_input("please input a number:"))except ValueError: print("第一个运算数字输入非数字") try: b=int(raw_input("please input another number:"))except Val

一个简单的小例子让你明白c#中的委托-终于懂了!

模拟主持人发布一个问题,由多个嘉宾来回答这个问题. 分析:从需求中抽出Host (主持人) 类和Guests (嘉宾) 类. 作为问题的发布者,Host不知道问题如何解答.因此它只能发布这个事件,将事件委托给多个嘉宾去处理.因此在Host 类定义事件,在Guests类中定义事件的响应方法.通过多番委托的"+="将响应方法添加到事件列表中,最终 Host 类将触发这个事件.实现过程如下: 代码其实很少下面贴出来所有代码: QuestionArgs.cs view plaincopy to