Java Code for calculating Leap Year

2019-01-01 07:24发布

问题:

I am following \"The Art and Science of Java\" book and it shows how to calculate a leap year. The book uses ACM Java Task Force\'s library.

Here is the code the books uses:

import acm.program.*;

public class LeapYear extends ConsoleProgram {
    public void run()
    {

        println(\"This program calculates leap year.\");
        int year = readInt(\"Enter the year: \");     

        boolean isLeapYear = ((year % 4 == 0) && (year % 100 != 0) || (year % 400 == 0));

        if (isLeapYear)
        {
            println(year + \" is a leap year.\");
        } else
            println(year + \" is not a leap year.\");
    }

}

Now, this is how I calculated the leap year.

import acm.program.*;

public class LeapYear extends ConsoleProgram {
    public void run()
    {

        println(\"This program calculates leap year.\");
        int year = readInt(\"Enter the year: \");

        if ((year % 4 == 0) && year % 100 != 0)
        {
            println(year + \" is a leap year.\");
        }
        else if ((year % 4 == 0) && (year % 100 == 0) && (year % 400 == 0))
        {
            println(year + \" is a leap year.\");
        }
        else
        {
            println(year + \" is not a leap year.\");
        }
    }
}

Is there anything wrong with my code or should i use the one provided by the book ?

EDIT :: Both of the above code works fine, What i want to ask is which code is the best way to calculate the leap year.

回答1:

They look the same to me, though note that this line in your code has some redundancy:

else if ((year % 4 == 0) && (year % 100 == 0) && (year % 400 == 0))

could be replaced by:

else if (year % 400 == 0)

If a number is a multiple of 400 then it\'s automatically also a multiple of 100 and 4.

edit: (7 years later!)

Please note that the above assumes the presence of the preceding if ((year % 4 == 0) && year % 100 != 0) from the original question!

cletus\'s answer should be the accepted one: https://stackoverflow.com/a/1021373/8331

(I\'d delete my own answer, but I can\'t since it\'s the accepted on)



回答2:

The correct implementation is:

public static boolean isLeapYear(int year) {
  Calendar cal = Calendar.getInstance();
  cal.set(Calendar.YEAR, year);
  return cal.getActualMaximum(Calendar.DAY_OF_YEAR) > 365;
}

But if you are going to reinvent this wheel then:

public static boolean isLeapYear(int year) {
  if (year % 4 != 0) {
    return false;
  } else if (year % 400 == 0) {
    return true;
  } else if (year % 100 == 0) {
    return false;
  } else {
    return true;
  }
}


回答3:

I suggest you put this code into a method and create a unit test.

public static boolean isLeapYear(int year) {
    assert year >= 1583; // not valid before this date.
    return ((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0);
}

In the unit test

assertTrue(isLeapYear(2000));
assertTrue(isLeapYear(1904));
assertFalse(isLeapYear(1900));
assertFalse(isLeapYear(1901));


回答4:

java.time.Year::isLeap

I\'d like to add the new java.time way of doing this with the Year class and isLeap method:

java.time.Year.of(year).isLeap()


回答5:

new GregorianCalendar().isLeapYear(year);


回答6:

Pseudo code from Wikipedia translated into the most compact Java

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


回答7:

Most Efficient Leap Year Test:

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

This is an excerpt from my detailed answer at https://stackoverflow.com/a/11595914/733805



回答8:

From JAVA\'s GregorianCalendar sourcecode:

/**
 * Returns true if {@code year} is a leap year.
 */
public boolean isLeapYear(int year) {
    if (year > changeYear) {
        return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0);
    }

    return year % 4 == 0;
}

Where changeYear is the year the Julian Calendar becomes the Gregorian Calendar (1582).

The Julian calendar specifies leap years every four years, whereas the Gregorian calendar omits century years which are not divisible by 400.

In the Gregorian Calendar documentation you can found more information about it.



回答9:

It\'s almost always wrong to have repetition in software. In any engineering discipline, form should follow function, and you have three branches for something which has two possible paths - it\'s either a leap year or not.

The mechanism which has the test on one line doesn\'t have that issue, but generally it would be better to separate the test into a function which takes an int representing a year and returns a boolean representing whether or not the year is a leap year. That way you can do something with it other that print to standard output on the console, and can more easily test it.

In code which is known to exceed its performance budget, it\'s usual to arrange the tests so that they are not redundant and perform the tests in an order which returns early. The wikipedia example does this - for most years you have to calculate modulo 400,100 and 4, but for a few you only need modulo 400 or 400 and 100. This is a small optimisation in terms of performance ( at best, only one in a hundred inputs are effected ), but it also means the code has less repetition, and there\'s less for the programmer to type in.



回答10:

If you are using java8 :

java.time.Year.of(year).isLeap()

Java implementation of above method:

public static boolean isLeap(long year) {
        return ((year & 3) == 0) && ((year % 100) != 0 || (year % 400) == 0);
    }


回答11:

You can ask the GregorianCalendar class for this:

boolean isLeapyear = new GregorianCalendar().isLeapYear(year);


回答12:

This is what I came up with. There is an added function to check to see if the int is past the date on which the exceptions were imposed(year$100, year %400). Before 1582 those exceptions weren\'t around.

import java.util.Scanner;

public class lecture{


public static void main(String[] args) {
    boolean loop=true;
    Scanner console = new Scanner( System.in );
    while (loop){
        System.out.print( \"Enter the year: \" );

        int year= console.nextInt();
        System.out.println( \"The year is a leap year: \"+ leapYear(year) );
        System.out.print( \"again?: \" );
        int again = console.nextInt();
        if (again == 1){
            loop=false;
        }//if
    }
}
public static boolean leapYear ( int year){
    boolean leaped = false;
    if (year%4==0){
        leaped = true;
        if(year>1582){
            if (year%100==0&&year%400!=0){
                leaped=false;
            }
        }
    }//1st if
    return leaped;
}
} 


回答13:

public static void main(String[] args)
{

String strDate=\"Feb 2013\";
        String[] strArray=strDate.split(\"\\\\s+\");        

        Calendar cal = Calendar.getInstance();
        cal.setTime(new SimpleDateFormat(\"MMM\").parse(strArray[0].toString()));
        int monthInt = cal.get(Calendar.MONTH);
        monthInt++;
        cal.set(Calendar.YEAR, Integer.parseInt(strArray[1]));          
        strDate=strArray[1].toString()+\"-\"+monthInt+\"-\"+cal.getActualMaximum(Calendar.DAY_OF_MONTH);

        System.out.println(strDate);    



}


回答14:

    import java.util.Scanner;

    public class LeapYear {
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Scanner input = new Scanner(System.in);
        System.out.print(\"Enter the year then press Enter : \");
        int year = input.nextInt();

        if ((year < 1580) && (year % 4 == 0)) {
            System.out.println(\"Leap year: \" + year);
        } else {
            if ((year % 4 == 0) && (year % 100 != 0) || (year % 400 == 0)) {
                System.out.println(\"Leap year: \" + year);
            } else {
                System.out.println(year + \" not a leap year!\");
            }

        }
    }
}


回答15:

As wikipedia states algorithm for the leap year should be

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

Here is a sample program how to check for leap year.



回答16:

Your code, as it is, without an additional class, does not appear to work for universal java. Here is a simplified version that works anywhere, leaning more towards your code.

import java.util.*;
public class LeapYear {
    public static void main(String[] args) {
        int year;
        {
            Scanner scan = new Scanner(System.in);
            System.out.println(\"Enter year: \");
            year = scan.nextInt();

            if ((year % 4 == 0) && year % 100 != 0) {
                System.out.println(year + \" is a leap year.\");
            } else if ((year % 4 == 0) && (year % 100 == 0)
                    && (year % 400 == 0)) {
                System.out.println(year + \" is a leap year.\");
            } else {
                System.out.println(year + \" is not a leap year.\");
            }
        }
    }
}

Your code, in context, works just as well, but note that book code always works, and is tested thoroughly. Not to say yours isn\'t. :)



回答17:

easiest way ta make java leap year and more clear to understandenter code here

import  java.util.Scanner;

class que19{

public static void main(String[] args) {

    Scanner input=new Scanner(System.in);

    double a;

    System.out.println(\"enter the year here \");
    a=input.nextDouble();
    if ((a % 4 ==0 ) && (a%100!=0) || (a%400==0)) {
        System.out.println(\"leep year\");

    }
    else {
        System.out.println(\"not a leap year\");
    }
}

}



回答18:

With the course of : https://tmc.mooc.fi , that one of the exercises was this kind of issue, I wrote this answer:

import java.util.Scanner;

public class LeapYear {

    public static void main(String[] args) {
        Scanner reader = new Scanner(System.in);
        System.out.println(\"Type a year: \");

        int year = Integer.parseInt(reader.nextLine());

        if (year % 400 == 0 && year % 100 == 0 && year % 4 == 0) {
            System.out.println(\"The year is a leap year\");
        } else
         if (year % 4 == 0 && year%100!=0 ) {
            System.out.println(\"The year is a leap year\");
        } else 
        {
            System.out.println(\"The year is not a leap year\");
        }

    }
}


回答19:

this answer is great but it won\'t work for years before Christ (using a proleptic Gregorian calendar). If you want it to work for B.C. years, then use the following adaptation:

public static boolean isLeapYear(final int year) {
    final Calendar cal = Calendar.getInstance();
    if (year<0) {
        cal.set(Calendar.ERA, GregorianCalendar.BC);
        cal.set(Calendar.YEAR, -year);
    } else
        cal.set(Calendar.YEAR, year);
    return cal.getActualMaximum(Calendar.DAY_OF_YEAR) > 365;
}

You can verify that for yourself by considering that year -5 (i.e. 4 BC) should be pronounced as a leap year assuming a proleptic Gregorian calendar. Same with year -1 (the year before 1 AD). The linked to answer does not handle that case whereas the above adapted code does.



回答20:

import javax.swing.*;
public class LeapYear {
    public static void main(String[] args) {
    int year;
String yearStr = JOptionPane.showInputDialog(null, \"Enter radius: \" );

year = Integer.parseInt( yearStr );

boolean isLeapYear;
isLeapYear = (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);  

 if(isLeapYear){ 
JOptionPane.showMessageDialog(null, \"Leap Year!\"); 
 }  
 else{
JOptionPane.showMessageDialog(null, \"Not a Leap Year!\"); 
    }
    }
    }


回答21:

boolean leapYear = ( ( year % 4 ) == 0 );