41

「Javaの芸術と科学」の本をフォローしていますが、うるう年の計算方法を示しています。この本は、ACM JavaTaskForceのライブラリを使用しています。

本が使用するコードは次のとおりです。

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.");
    }

}

さて、これがうるう年の計算方法です。

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.");
        }
    }
}

私のコードに何か問題がありますか、それとも本で提供されているものを使用する必要がありますか?

編集::上記のコードは両方とも正常に機能します。私が聞きたいのは、うるう年を計算するための最良の方法はどちらのコードかということです。

4

21 に答える 21

98

正しい実装は次のとおりです。

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

しかし、このホイールを再発明する場合は、次のようにします。

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;
  }
}
于 2009-06-20T10:21:47.517 に答える
38

java.time.Year::isLeap

クラスとメソッドjava.timeを使用してこれを行う新しい方法を追加したいと思います。YearisLeap

java.time.Year.of(year).isLeap();
于 2016-05-22T22:32:21.430 に答える
29

このコードをメソッドに入れて、単体テストを作成することをお勧めします。

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

単体テストで

assertTrue(isLeapYear(2000));
assertTrue(isLeapYear(1904));
assertFalse(isLeapYear(1900));
assertFalse(isLeapYear(1901));
于 2009-06-20T09:57:13.900 に答える
11

最もコンパクトな Java に変換されたウィキペディアの疑似コード

(year % 400 == 0) || ((year % 4 == 0) && (year % 100 != 0))
于 2010-05-28T20:40:00.050 に答える
6

最も効率的なうるう年テスト:

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

これは、 https://stackoverflow.com/a/11595914/733805での詳細な回答からの抜粋です。

于 2012-07-21T23:53:59.933 に答える
5

JAVA の GregorianCalendar ソースコードから:

/**
 * 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;
}

changeYear は、ユリウス暦がグレゴリオ暦 (1582 年) になる年です。

ユリウス暦では 4 年ごとにうるう年が指定されますが、グレゴリオ暦では 400 で割り切れない世紀の年が省略されます。

グレゴリオ暦のドキュメントで、それに関する詳細情報を見つけることができます。

于 2016-06-01T14:18:16.667 に答える
3

ソフトウェアで繰り返しを行うことは、ほとんどの場合間違っています。どの工学分野でも、フォームは機能に従う必要があります。うるう年かどうかにかかわらず、2つの可能なパスを持つものに対して3つのブランチがあります。

1行にテストがあるメカニズムにはその問題はありませんが、一般に、テストを、年を表すintを取り、年がうるう年であるかどうかを表すブール値を返す関数に分割する方がよいでしょう。 。そうすれば、コンソールの標準出力に出力する以外のことを実行でき、より簡単にテストできます。

パフォーマンスバジェットを超えることがわかっているコードでは、通常、テストが冗長にならないように配置し、早期に戻る順序でテストを実行します。ウィキペディアの例ではこれを行います。ほとんどの場合、400、100、および4を法として計算する必要がありますが、400、400、および100を法として計算する必要がある場合もあります。これは、パフォーマンスの観点からは小さな最適化です(せいぜい、100分の1のみ)。入力は影響を受けます)が、コードの繰り返しが少なく、プログラマーが入力する回数が少ないことも意味します。

于 2009-06-20T10:07:16.800 に答える
2

これについては、 GregorianCalendarクラスに問い合わせることができます。

boolean isLeapyear = new GregorianCalendar().isLeapYear(year);
于 2016-06-01T14:46:28.583 に答える
0

ウィキペディアが述べているように、うるう年のアルゴリズムは

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

うるう年をチェックするサンプルプログラムを次に示します。

于 2015-05-24T15:45:47.357 に答える
0

あなたのコードは、追加のクラスなしでは、ユニバーサル Java では機能しないようです。これは、どこでも機能する簡略化されたバージョンで、コードに傾倒しています。

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.");
            }
        }
    }
}

コンテキスト内のコードは同様に機能しますが、本のコードは常に機能し、徹底的にテストされていることに注意してください。あなたがそうではないと言っているわけではありません。:)

于 2016-01-21T16:37:00.207 に答える
0
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);    



}
于 2013-10-23T14:41:31.397 に答える
0

Kotlin での回答:

fun isLeapYear(year: Int): Boolean =
    when {
        year % 4 != 0 -> false
        year % 100 == 0 -> year % 400 == 0
        else -> true
    }
于 2021-09-12T00:21:36.657 に答える
-1
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!"); 
    }
    }
    }
于 2013-04-15T17:54:20.173 に答える
-2
boolean leapYear = ( ( year % 4 ) == 0 );
于 2012-12-06T20:02:03.827 に答える