如何找到闰年编程用C如何找到闰年编程用C(How to find leap year program

2019-05-10 15:34发布

我做了用C找到进入一年是否是闰年的程序。 但遗憾的是它不工作很好。 它说,一年是飞跃和上一年度未飞跃。

#include<stdio.h>
#include<conio.h>
int yearr(int year);
void main(void)
{
    int year;
    printf("Enter a year:");
    scanf("%d",&year);
    if(!yearr(year))
    {
        printf("It is a leap year.");
    }
    else
    {
    printf("It is not a leap year");
    }


getch();
}
int yearr(int year)
{
    if((year%4==0)&&(year/4!=0))
    return 1;
    else
    return 0;
}

看完评论后,我编辑我的编码为:

#include<stdio.h>
#include<conio.h>
int yearr(int year);
void main(void)
{
    int year;
    printf("Enter a year:");
    scanf("%d",&year);
    if(!yearr(year))
    {
        printf("It is a leap year.");
    }
    else
    {
    printf("It is not a leap year");
    }


getch();
}
int yearr(int year)
{
    if((year%4==0)
    {
    if(year%400==0)
    return 1;
    if(year%100==0)
    return 0; 
    }
    else
    return 0;
}

Answer 1:

你的逻辑来确定一个闰年是错误的。 这应该让你(维基百科)开始:

if year modulo 400 is 0
       then is_leap_year
else if year modulo 100 is 0
       then not_leap_year
else if year modulo 4 is 0
       then is_leap_year
else
       not_leap_year

x modulo y指的其余部分x除以y 。 例如,12模5是2。



Answer 2:

最有效的闰年测试:

if ((year & 3) == 0 && ((year % 25) != 0 || (year & 15) == 0))
{
    /* leap year */
}

此代码是有效的C,C ++,C#,Java和许多其他类似C语言。 代码利用单个TRUE / FALSE表达式,由三个独立的测试:

  • 4年测试: year & 3
  • 100年的试验: year % 25
  • 第400年的试验: year & 15

这个代码是如何工作的全面讨论下面出现,但首先维基百科的算法的讨论呼吁:

维基百科的算法是低效/不可靠

维基百科出版了伪码算法(参见: 维基百科:闰年-算法 ),已经过常量编辑,观点和破坏。

不实现维基百科算法!

其中一个站立时间最长(和低效的)维基百科的算法出现如下:

if year modulo 400 is 0 then
   is_leap_year
else if year modulo 100 is 0 then
   not_leap_year
else if year modulo 4 is 0 then
   is_leap_year
else
   not_leap_year

上面的算法是低效的,因为它总是甚至数年,将很快失败了“4年试验”(模4测试)首位,而其的75%的时间执行第400年和100年的测试! 通过重新排序的算法显著执行4年的测试首先我们加快速度。

“最高效”的伪代码算法

我提供以下算法维基百科(不止一次):

if year is not divisible by 4 then not leap year
else if year is not divisible by 100 then leap year
else if year is divisible by 400 then leap year
else not leap year

这个“最高效的”伪代码简单地改变测试的顺序,以便通过4分割首先发生,其次是少频繁出现的测试。 因为“年”不通过时的4个75%的分成,该算法在四分之三的情况下,只有一个测试后结束。

注:我已经打了不同的维基百科的编辑,以提高出版那里的算法,认为很多新手和专业程序员很快到达维基百科页面(由于顶部搜索引擎列表)并执行维基百科伪代码没有任何进一步的研究。 维基百科的编辑否定和删除每次尝试我做了改善,注释,甚至仅仅脚注发布的算法。 显然,他们觉得找到效率是程序员的问题。 这可能是真的,但很多程序员都太匆忙进行扎实的研究!

讨论“最高效”闰年TEST

按位与到位模数:

我已经更换两个维基百科的算法模运算与位与操作。 为什么和怎么样?

执行模计算需要除法。 一个编程电脑时,但编程嵌入你会发现,一个除法功能不能本身由CPU执行的小型设备的8位微控制器时不会经常三思这一点。 在这样的CPU,除法是涉及重复循环,比特移位一个艰巨的过程,以及加/减操作,这是非常慢的。 这是非常需要避免。

事实证明,两个大国的模可以使用位与运算来实现交替(参见: 维基百科:模操作-性能问题 ):

X%2 ^ N == X - (2 ^ N - 1)

许多优化编译器将其转换这样的模运算按位,和为贵,但对于更小,更流行的CPU不太先进的编译器可能不会。 按位与是每个CPU上的单个指令。

通过更换modulo 4modulo 400与测试& 3& 15 (见下文:“保减少数学”)我们可以确保最快码结果,而无需使用一个慢得多的除法运算。

不存在的两个电源,等于100。因此,我们不得不继续使用模运算第100年的试验,但100是由25所取代(见下文)。

保理,以简化计算方法如下:

除了使用按位与更换模运算,您可能会注意到维基百科的算法和优化的表达与另外两个争议:

  • modulo 100被替换为modulo 25
  • modulo 400被替换& 15

第100届年度测试使用modulo 25而非modulo 100 。 我们能做到这一点,因为100度的因素缩小到2×2×5×5,因为4年的测试已经检查的4个因素,我们可以消除100因子,留下25这种优化可能是微不足道的几乎每一个CPU执行(既是100和25配合在8位)。

第400年的测试采用& 15这相当于modulo 16 。 再次,我们可以这样做是因为400个因素出到2×2×2×2×5×5。我们可以消除其由第100年的试验测试25的因子,留下16.我们不能进一步减少16因为图8是200的一个因素,所以删除任何更多的因素会产生不必要的正面为一块诞辰200年。

第400年的优化是8位CPU大幅重要的,第一,因为它避免了划分; 但是,更重要的是,因为该值400是这是更为困难的8位CPU在处理一个9位数字。

短路逻辑AND / OR操作:

使用最后,也是最重要的,最优化的短路逻辑AND(“&&”)和OR(“||”)操作符(见: 维基百科:短路计算 ),这是大多数类似C语言实现的。 短路运营商之所以如此命名,是因为他们也懒得去评估右侧表达,如果左侧的表达,其本身决定了操作的结果。

例如:如果年份是2003年,那么year & 3 == 0是假的。 没有办法,关于逻辑的右侧和测试可以使结果真实,所以没有别的获取评估。

通过首先进行的第4年的测试中,只有4年的试验(一个简单的按位AND)进行评估的时间四分之三(75%)。 这大大加快了程序的执行,特别是因为它避免了必要的100年测试(模25操作)的划分。

注:括号ON PLACEMENT

一位评论者认为括号在我的代码是放错了地方,并建议子表达式周围集结逻辑运算符(而不是周围的逻辑OR),具体如下:

if (((year & 3) == 0 && (year % 25) != 0) || (year & 15) == 0) { /* LY */ }

以上是不正确。 逻辑运算符具有比逻辑或更高的优先级,将有或没有新的括号先计算。 周围的逻辑括号和参数没有任何影响。 这可能会导致一个完全消除的子类别:

if ((year & 3) == 0 && (year % 25) != 0 || (year & 15) == 0) { /* LY */ }

但是,在上述两种情况下,逻辑OR(第400年的试验)的右侧几乎每一次评估(即年不是4和100整除)。 因此,一个有用的优化已经被错误地淘汰。

在我的原代码中的括号实现最优化的解决方案:

if ((year & 3) == 0 && ((year % 25) != 0 || (year & 15) == 0)) { /* LY */ }

这里,逻辑OR仅评估(由于短路和的)年被4整除。 逻辑OR的右侧仅评估(由于短路OR的)年被4整除和100。

注:对于C / C ++程序员

C / C ++程序员可能会觉得这种表达更加优化:

if (!(year & 3) && ((year % 25) || !(year & 15))) { /* LY */ }

这不是更优化! 虽然明确== 0!= 0测试被删除,他们变得含蓄,并且仍然执行。 更糟的是,代码不再有效如C#,其中强类型语言year & 3计算结果为int ,但是逻辑AND( && ),OR( || )和NOT( ! !运算符需要bool参数。



Answer 3:

int isLeapYear(int year)
{
   return (year % 400 == 0) || ( ( year % 100 != 0) && (year % 4 == 0 ));
}


Answer 4:

这可能是正确的解决方案。 在维基百科上给出的算法是不对的。

-(BOOL)isLeapYear: (int)year{    

    if(year%4==0){
      if(year%100!=0){
        return YES;
     }
     else if(year%400!=0){
        return YES;
     }
     else return NO;
   }

    else return NO;
  }


Answer 5:

尽管通过400首先将逻辑是无懈可击,它并不像第一除以4为计算上有效的。 你可以做到这一点与逻辑:

#define LEAPYEAR(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))

这对于每一个值除以4,但对他们的3/4,测试结束那里。 对于通过第一测试1/4,它然后通过100将,消除24/25值; 对于剩下的1出100,它除以400也是如此,拿出一个最终的答案。 当然,这是不是一个巨大的节省。



Answer 6:

从上闰年维基百科的文章 :

if (year modulo 4 is 0) and (year modulo 100 is not 0) or (year modulo 400 is 0)
   then is_leap_year
else
   not_leap_year


Answer 7:

与您的代码的问题是,你正在返回从非零值yearr ,如果你认为今年是闰年。 所以,你不需要! 在你的if语句。



Answer 8:

http://www.wwu.edu/depts/skywise/leapyear.html

闰年规则

有一个闰年,每年数为四整除完美 - 除了多年来它们是由100整除双方而不是400的规则效果世纪年内第二部分整除。 例如; 本世纪1600年和2000年是闰年,但世纪年1700,1800和1900都没有。 这意味着,三次出每四百年也有闰年间八年。



Answer 9:

 if(year%400 ==0 || (year%100 != 0 && year%4 == 0))
    {
        printf("Year %d is a leap year",year);
    }
    else
    {
        printf("Year %d is not a leap year",year);
    }

改变它像上面。 另请阅读此 。



Answer 10:


    #include 
    void main(void)
    {
        int year;
        printf("Enter a year to check if it is Leap Year\n");
        scanf("%d",&year);
        if(year%400==0) /* Why  mod 400 */
            printf("%d is a Leap Year\n",year);
        else if(year%100==0) /*  Why  mod 100  */
            printf("%d is not a Leap Year\n",year);
        else if(year%4==0)
            printf("%d is a Leap Year\n",year);
        else
            printf("%d is not a Leap Year\n",year);

    }



Answer 11:

I used this code:

#include <stdio.h>

int main()
{
    int yr;
    printf ("Enter a year \n");
    scanf ("%d", &yr);

    if (yr%400 == 0)
        printf("\n LEAP YEAR.");

    else if (yr%4==0 && yr%100!=0)
        printf("\n LEAP YEAR.");
    else
        printf ("\n NOT LEAP YEAR.");
}


Answer 12:

至于其他也提到条件闰年是不正确的。 这应该:

int yearr(int year)  
{  
    if(((year%4 == 0) && (year%100 !=0)) || (year%400==0))  
        return 1;    
    else    
        return 0;    
}  

在这里读它如何检查闰年用C 。



Answer 13:

凯文的答案提供了一个最佳的8操作测试(使用XOR常数),但如果你正在寻找的东西更可读一点,试试这个9运行试验。

year % 4 == 0 && !((year % 100 == 0) ^ (year % 400 == 0))

真值表(year % 100 == 0) ^ (year % 400 == 0)

                              (year % 100 == 0) ^ (year % 400 == 0)
100 doesnt divide year     .    F
only 100 divides year      .    T
100 and 400 divides year   .    F

现在!(year % 100 == 0) ^ (year % 400 == 0)给你想要的东西。



Answer 14:

计算最大/月为最后一天:1..12,年:1..3999

maxDays = month == 2 ?
  28 + ((year & 3) == 0 && ((year % 25) != 0 || (year & 15) == 0)) :
  30 + ((month & 1) ^ (month > 7));


Answer 15:

#define is_leap(A) !((A) & 3)

只要确保你不进入负一年:)



文章来源: How to find leap year programatically in C
标签: c leap-year