最近偶然翻出几年前的一段代码,当时是为了做一个电子钟写的代码,代码的主要作用是计算两年之间的闰年个数
当时的代码是这样写的:
#define RunNian(a)((a%4==0)&&(a%100))||(a%400==0)>0? 1:0
unsigned int NumberEfLeapYear1(unsigned int year1,unsigned int year2)
{
unsigned int i;
unsigned int con=0;
if((year1==0)&&(year2==0))
return 0;
if(year2<year1)
return 0;
for(i=year1;i<year2;i++)
{
if( RunNian(i) )
{
con++;
}
}
if (year1 == 0)
con--;
return con ;
}
解决的问题的方法简单粗暴,就是通过循环累加两年之间闰年,程序当时运行也没有什么问题,就一直这样用,今天在看到这段代码的时候,就一个感觉,
效率低下。
于是就想通过算法的方式解决问题,通过网络搜索,结果很不满意,于是通过苦苦思索,终于找到了计算方法
#define RunNian(a)((a%4==0)&&(a%100))||(a%400==0)>0? 1:0
unsigned int NumberEfLeapYear1(unsigned int year1,unsigned int year2)
{
unsigned int a,b;
if((year1==0)&&(year2==0))
return 0;
year2 --;//不算最后一年
if(year2<year1)
return 0; a = year1/4-year1/100+year1/400;
b = year2/4-year2/100+year2/400;
if(year1!=0)
{
if (RunNian(year1))
return b-a+1;
}
return b-a;
}
思路是这样的,计算0年至每一年的之间的闰年个数,然后相减,差就是两年之间的闰年个数,
那么代码结果正确吗?
我写了一段代码验证一下
int main (void)
{
int a,b,c,d;
int i,n;
a = 0; b = 2200;
for (n=a ; n<=b ; n++)
{
for (i=n ; i<=b ; i++)
{
c = NumberEfLeapYear(n,i);
d = NumberEfLeapYear1(n,i);
if (c != d)
{
printf ("n=%d,i=%d\n",n,i);
printf ("end!\n");
printf ("c=%d ",c);
printf ("d=%d\n",d);
break;
}
}
if(c!=d)
break;
}
if((n==b+1) && (i==b+1))
printf ("ok!\n");
return 0;
}

结果完全正确
比较一下效率
int main (void)
{
int a,b,c,d;
int i,n;
a = 0; b = 9999;
for (n=a ; n<=b ; n++)
{
for (i=n ; i<=b ; i++)
{
c = NumberEfLeapYear1(n,i);
}
}
return 0;
}
累加函数时间

跑完0~9999年耗时5.612S
改成计算函数

仅耗时0.7384S
相差很悬殊
看来算法真的很重要
当时的代码是这样写的:
#define RunNian(a)((a%4==0)&&(a%100))||(a%400==0)>0? 1:0
unsigned int NumberEfLeapYear1(unsigned int year1,unsigned int year2)
{
unsigned int i;
unsigned int con=0;
if((year1==0)&&(year2==0))
return 0;
if(year2<year1)
return 0;
for(i=year1;i<year2;i++)
{
if( RunNian(i) )
{
con++;
}
}
if (year1 == 0)
con--;
return con ;
}
解决的问题的方法简单粗暴,就是通过循环累加两年之间闰年,程序当时运行也没有什么问题,就一直这样用,今天在看到这段代码的时候,就一个感觉,
效率低下。
于是就想通过算法的方式解决问题,通过网络搜索,结果很不满意,于是通过苦苦思索,终于找到了计算方法
#define RunNian(a)((a%4==0)&&(a%100))||(a%400==0)>0? 1:0
unsigned int NumberEfLeapYear1(unsigned int year1,unsigned int year2)
{
unsigned int a,b;
if((year1==0)&&(year2==0))
return 0;
year2 --;//不算最后一年
if(year2<year1)
return 0; a = year1/4-year1/100+year1/400;
b = year2/4-year2/100+year2/400;
if(year1!=0)
{
if (RunNian(year1))
return b-a+1;
}
return b-a;
}
思路是这样的,计算0年至每一年的之间的闰年个数,然后相减,差就是两年之间的闰年个数,
那么代码结果正确吗?
我写了一段代码验证一下
int main (void)
{
int a,b,c,d;
int i,n;
a = 0; b = 2200;
for (n=a ; n<=b ; n++)
{
for (i=n ; i<=b ; i++)
{
c = NumberEfLeapYear(n,i);
d = NumberEfLeapYear1(n,i);
if (c != d)
{
printf ("n=%d,i=%d\n",n,i);
printf ("end!\n");
printf ("c=%d ",c);
printf ("d=%d\n",d);
break;
}
}
if(c!=d)
break;
}
if((n==b+1) && (i==b+1))
printf ("ok!\n");
return 0;
}

结果完全正确
比较一下效率
int main (void)
{
int a,b,c,d;
int i,n;
a = 0; b = 9999;
for (n=a ; n<=b ; n++)
{
for (i=n ; i<=b ; i++)
{
c = NumberEfLeapYear1(n,i);
}
}
return 0;
}
累加函数时间

跑完0~9999年耗时5.612S
改成计算函数

仅耗时0.7384S
相差很悬殊
看来算法真的很重要