найти следующий високосный год Java

Код работает, когда первый год является високосным, поэтому, если я скажу, что это 2004 год, он вернет 2008 год, но если начальный год не является високосным, он ничего не вернет. Как бы я вывел это, если, например: данный год был 2001, 2002 или 2003, следующим високосным годом будет 2004. Я знаю, что цикл while имеет смысл, но я не знаю, что в него вставить. ТАКЖЕ я могу использовать только базовое форматирование java, поэтому не вводите классы, такие как java.time.Year

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

public static int nextLeapYear(int year) {
  int nextLeap = 0;

  if (leapYear(year)) {
    nextLeap = nextLeap + 4;
  } else {
    while (!leapYear(year)) {
      nextLeap++;
    }
    nextLeap += 1;
  }
  year += nextLeap;
  return year;
}

person ayojava    schedule 14.10.2020    source источник
comment
Вы также можете принять свой собственный ответ (через время, я думаю, 12 часов).   -  person Ole V.V.    schedule 14.10.2020
comment
Если это упражнение, то хорошее. Для производственного кода не следует и не следует производить собственный расчет високосного года, а следует оставить его для `Year.isLeap() или другой хороший библиотечный метод.   -  person Ole V.V.    schedule 14.10.2020


Ответы (5)


Конечно, это не требует большой обработки. Но если вы хотите повысить эффективность своей программы, вы можете рассмотреть следующее:

  • Все високосные годы должны делиться на 4. Но не все годы, делящиеся на 4, являются високосными. Итак, сначала проверьте, не делится ли число на 4. Это будет 75% случаев. В этом случае верните false.
   if (year % 4 != 0) {
        return false;
   }
  • Пока вы продолжаете, year must be divisible by 4 просто убедитесь, что это не столетний год. Это будет оцениваться в 25% случаев и возвращать true в 24% случаев.
   if (year % 100 != 0) {
       return true;
   }
  • наконец, единственная непроверенная категория — это годы, деленные на 400. Если мы попали сюда по логике, то это должен быть столетний год. Так что возвращайтесь соответственно. Это будет оцениваться как true в 0,25% случаев.
  return year % 400 == 0;

person WJS    schedule 14.10.2020

Ваш код сломан несколькими способами:

  1. Вы говорите: если данный год високосный, то следующий високосный год будет через 4 года. Это неверно. Если вы пройдете в 1896 году, ваш алгоритм вернет 1900, но это неправильно; 1896 год — високосный, а 1900 — нет.

  2. Ваш код isLeapYear будет намного легче читать, если вы выйдете раньше. Этот метод должен иметь много операторов возврата и иметь меньше отступов.

  3. Ваш цикл while будет задавать один и тот же вопрос снова и снова, и если вы зададите один и тот же вопрос стабильному методу (а ваш метод isLeapYear стабилен), вы получите один и тот же ответ, что приведет к бесконечному циклу. Предположительно, вам не нужен while(!leapYear(year)), вам нужен while(!leapYear(year + nextLeap)), и вы не хотите увеличивать значение nextLeap еще раз после цикла while.

  4. на самом деле крайний случай: если заявленный год уже год, прибавлять 4 - вообще не надо. Подумайте об этом: вы можете просто исключить часть if/else. Ваш код будет просто nextLeap, циклом while и оператором возврата. 3-х лайнер, если вы делаете правильно.

person rzwitserloot    schedule 14.10.2020
comment
Спасибо вам за помощь! Я все еще учусь, поэтому я могу принять все предложения. Однако я последовал вашему совету и изменил код на int nextLeap = 0; while(leapYear(year + nextLeap) == false){ nextLeap++; } год += следующий скачок; год возвращения; Но хотя он работал, когда данный год НЕ был високосным, он не возвращал мне следующий високосный год, когда данный год БЫЛ високосным. Так не нужен ли мне какой-то оператор if? - person ayojava; 14.10.2020
comment
Нет, не знаешь. Вам нужно изменить 1 символ.... :) - person rzwitserloot; 14.10.2020

РЕДАКТИРОВАТЬ: Я понял это, ура!

для тех, кто борется с этим, это то, что сработало для меня :)

public static boolean leapYear(int year) {
    if(year % 4 == 0)
    {
        if( year % 100 == 0)
        {
            // year is divisible by 400, hence the year is a leap year
            if ( year % 400 == 0)
                return true;
            else
                return false;
        }
        else
            return true;
    }
    else
        return false;
    }



public static int nextLeapYear (int year) {
    int nextLeap = 0;
         while(leapYear(year + nextLeap) == false){
             nextLeap++;
        
         }
        
        if(leapYear(year) == true)
            nextLeap += 4;
        
        year += nextLeap;
        return year;

    }
person ayojava    schedule 14.10.2020
comment
Это скачок вперед. nextLeapYear(2096) возвращает 2100, но 2100 не будет високосным годом (и leapYear(2100) правильно возвращает false). - person Ole V.V.; 14.10.2020
comment
Заведите привычку заключать в скобки ({}) операторы return и любые другие действия с одним оператором, которые могут попасть в блок. Это сэкономит вам время на отладку в будущем. - person WJS; 14.10.2020

Кажется, не так просто получить nextLeapYear() 100 % правильное решение. Позвольте мне предложить более простой способ думать об этом, который также, как я считаю, упростит правильный код и/или исправит любую ошибку, которая может быть.

Объявите переменную candidateLeapYear для хранения года, о котором мы еще не знаем, будет ли он следующим високосным годом после year. Инициализируйте его как year + 1, так как мы знаем, что следующий високосный год должен быть строго больше year. В цикле проверьте, является ли candidateLeapYear високосным годом (используйте другой метод), и, пока это не так, увеличьте на 1. Когда цикл завершается, candidateLeapYear содержит следующий високосный год. Верни это.

Удачного кодирования.

person Ole V.V.    schedule 14.10.2020

Каждый год, который точно делится на четыре, является високосным, за исключением годов, которые точно делятся на 100, но эти столетние годы являются високосными, если они точно делятся на 400. Например, 1700, 1800 и 1900 годы являются високосными. не високосные годы, а 1600 и 2000 годы. - Военно-морская обсерватория США

Вы можете значительно упростить функцию, leapYear как показано ниже:

public static boolean leapYear(int year) {
  return year % 400 == 0 || (year % 4 == 0 && year % 100 != 0);
}

Демонстрация:

public class Main {
    public static void main(String[] args) {
        // Test
        System.out.println(leapYear(1999));
        System.out.println(leapYear(2000));
        System.out.println(leapYear(1900));
        System.out.println(leapYear(1904));
    }

    public static boolean leapYear(int year) {
        return year % 400 == 0 || (year % 4 == 0 && year % 100 != 0);
    }
}

Вывод:

false
true
false
true

Затем вы можете использовать его в функции nextLeapYear, как показано ниже:

public class Main {
    public static void main(String[] args) {
        // Test
        System.out.println(nextLeapYear(1999));
        System.out.println(nextLeapYear(2000));
        System.out.println(nextLeapYear(2001));
    }

    public static int nextLeapYear(int year) {
        // If year is already a leap year, return year + 4
        if (leapYear(year)) {
            return year + 4;
        }

        // Otherwise, keep incrementing year by one until you find a leap year
        while (!leapYear(year)) {
            year++;
        }

        return year;
    }

    public static boolean leapYear(int year) {
        return year % 400 == 0 || (year % 4 == 0 && year % 100 != 0);
    }
}

Вывод:

2000
2004
2004

В рабочем коде следует использовать класс OOTB (Out-Of-The-Box), java.time.Year для обозначения года.

import java.time.Year;

public class Main {
    public static void main(String[] args) {
        // Test
        System.out.println(nextLeapYear(1999));
        System.out.println(nextLeapYear(2000));
        System.out.println(nextLeapYear(2001));
    }

    public static int nextLeapYear(int year) {
        Year yr = Year.of(year);
        // If year is already a leap year, return year + 4
        if (yr.isLeap()) {
            return yr.plusYears(4).getValue();
        }

        // Otherwise, keep incrementing year by one until you find a leap year
        while (!yr.isLeap()) {
            yr = yr.plusYears(1);
        }

        return yr.getValue();
    }
}

Вывод:

2000
2004
2004

Узнайте больше о современном API даты и времени на странице Trail: Date Time< /а>.

person Arvind Kumar Avinash    schedule 14.10.2020