Kwert-soft.ru

IT Софт для ПК
0 просмотров
Рейтинг статьи
1 звезда2 звезды3 звезды4 звезды5 звезд
Загрузка...

Java високосный год

Високосные годы

Надеюсь, вы отлично встретили новый год, и сейчас у вас отличное праздничное настроение. По крайней мере у меня это именно так — мы не пили никакого алкоголя, и чокнулись в полночь бокалами с водой из пятилитровой канистры, поэтому мы проснулись, погуляли, и тут я вспомнил одно из вчерашних поздравлений с Новым годом:

Желаю, чтобы в конце каждого года ты, вспоминая то, что было за последние 366 if ((year%4 == 0 and year%100 != 0) or (year%400 == 0)) else 365 дней, думал про себя:

— Ох, нифига себе, какой был экшен. Обязательно буду рассказывать внукам или напишу об этом потом книгу.

Итак, выше достаточно простой inline-способ определить количество дней в году (переменная year), который, по сути, полностью раскрывает их суть: в григорианском календаре високосными годами считаются те годы, порядковый номер которых либо кратен 4, но при этом не кратен 100, либо кратен 400. Иными словами, если год делится на 4 без остатка, но делится на 100 только с остатком, то он високосный, иначе — невисокосный, кроме случая, если он делится без остатка на 400 — тогда он всё равно високосный.

Например, 2013 год невисокосный, 1700, 1800 и 1900 — опять же невисокосные годы, а вот 2000, 2004, 2008 и 2012 — високосные.

Но что, если мы не помним, сколько дней в високосных (366 дней) и невисокосных (365 дней) годах, или просто хотим написать определение количества дней в году максимально быстро? Можно ли сделать так на Python? Конечно же, можно.

Итак, в Python есть модуль calendar. Он как раз отлично подходит для того, чтобы узнать, является ли тот или иной год високосным (или, например, сколько високосных годов в определённом интервале), определить количество дней в месяце, получить номер дня недели для определённой даты и так далее.

В частности, мы можем получить количество дней в каждом месяце года, и просто сложить.

Функция calendar.monthrange принимает номер года в качестве первого аргумента и номер месяца в качестве второго аргумента. Возвращает номер дня недели первого числа данного месяца и количество дней в данном месяце:

Соответственно, мы можем подсчитать общее количество дней для всех 12 месяцев, и получить таким образом количество дней для данного года:

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

Проверяем с помощью модуля timeit.

На то, чтобы выполнить её 1 миллион раз, требуется 13.69 секунд, если import calendar делается один раз в начале. Если import calendar делается каждый раз, тогда 14.49 секунд.

Теперь попробуем другой вариант. Он требует знания того, сколько дней в високосных и невисокосных годах, но зато он очень короткий:

И, как легко догадаться, он уже намного быстрее: 0.83 секунд, включая import calendar, и 0.26 секунд, если import calendar делается один раз в начале.

Давайте также посмотрим, сколько требуется времени самому первому варианту, с «ручным» подходом: 0.07 секунд для 2012 и 2013 и 0.12 секунд для 2000 (думаю, всем понятно, откуда берётся такая разница в скорости для этих годов).

Получается, что это и есть самый быстрый вариант из этих трёх:

Конечно, в большинстве случаев вы можете использовать любой из этих вариантов — в конце концов, при определении количества дней в одном, двух, десяти или ста годах вы вряд ли почувствуете какую-либо разницу.

Пишите, оптимизируйте, улучшайте, тестируйте и считайте производительность — но не забывайте о читаемости исходников ваших программ.

Читать еще:  Java io outputstream

С Новым годом! Удачи, счастья, радости и самосовершенствования в новом году.

Java код для расчета високосного года

Я следую за книгой «The Art and Science of Java», и она показывает, как вычислить високосный год. Книга использует библиотеку ACM Java Task Force.

Вот код, который используют книги:

Вот как я рассчитал високосный год.

Есть ли что-то неправильное в моем коде или я должен использовать тот, который указан в книге ?

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

21 Ответов

Но если вы собираетесь изобрести это колесо то:

Я предлагаю вам поместить этот код в метод и создать модульный тест.

В модульном тесте

java.time.Year::isLeap

Я бы хотел добавить новый способ java.time для этого с классом Year и методом isLeap :

Они выглядят одинаково для меня, хотя обратите внимание, что эта строка в вашем коде имеет некоторую избыточность:

может быть заменен на:

Если число кратно 400, то оно автоматически также кратно 100 и 4.

правка: (7 лет спустя!)

Обратите внимание, что вышесказанное предполагает наличие предшествующего if ((year % 4 == 0) && year % 100 != 0) из исходного вопроса!

(Я бы удалил свой собственный ответ, но я не могу, так как это принято на)

Псевдокод из Википедии переведен на самый компактный Java

Самый Эффективный Тест Високосного Года:

Это отрывок из моего подробного ответа по адресу https://stackoverflow.com/a/11595914/733805

Из исходного кода JAVA GregorianCalendar:

Где changeYear — это год, когда Юлианский календарь становится Григорианским (1582).

Юлианский календарь указывает високосный год каждые четыре года, в то время как Григорианский календарь опускает столетние годы, которые не делятся на 400.

В документации по Григорианскому календарю вы можете найти дополнительную информацию о нем.

Почти всегда неправильно иметь повторение в программном обеспечении. В любой инженерной дисциплине форма должна следовать за функцией, и у вас есть три ветви для чего — то, что имеет два возможных пути-это либо високосный год, либо нет.

Механизм, который имеет тест в одной строке, не имеет этой проблемы, но в целом было бы лучше разделить тест на функцию, которая принимает int, представляющий год, и возвращает логическое значение, представляющее, является ли год високосным или нет. Таким образом, вы можете сделать с ним что-то другое, что печатает стандартный вывод на консоли, и можете более легко протестировать его.

В коде, который, как известно, превышает свой бюджет производительности, обычно устраивают тесты так, чтобы они не были избыточными, и выполняют тесты в порядке, который возвращается раньше. Пример Википедии делает это — для большинства лет вам нужно вычислить по модулю 400,100 и 4, но для некоторых вам нужно только по модулю 400 или 400 и 100. Это небольшая оптимизация с точки зрения производительности ( в лучшем случае, только один из ста входов выполняется ), но это также означает, что код имеет меньше повторений, и программисту меньше нужно вводить.

Функция проверки високосных лет

Как часть одной из моих лабораторий AP Computer Science, я должен был написать функцию, чтобы определить, был ли год високосным годом или нет. В число комментариев входят несколько причин, почему я делал что-то, а также более подробную версию правил для високосных лет. Есть ли что-нибудь, что я мог бы сделать лучше или забыл?

5 ответов

Этот вопрос о високосных годах является интересным . и, кажется, является обрядом (когда вы делаете Конкуренция Целлера , вы должны получить, что рассмотрели тоже . ; -)

Читать еще:  Docker java 8

В Java, (и других языках), обычно возвращаются ранние. Вы можете использовать это в своих интересах, чтобы уменьшить вложение кода, выбрав, делать ли отрицательный или положительный тест в случае условностей. Вы делали это несколько раз в своем коде, но не всегда. Например, ваш код содержит:

У вас много кода внутри блока условий «if», но если вы отмените логику:

Вы сразу «не вложили» большую часть своего кода, что делает читаемость лучше.

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

Если у вас есть блок if-else, а if-side (истинная сторона) всегда выполняет return , тогда не требуется для else . Это может еще больше упростить код .

Выполняя эти изменения, мы получаем:

Как только мы получим такой код, очевидно, что последний код % 400 не нужен, и поскольку комментарии повторяются ( комментарии // дублируют большую часть того, что говорят спецификация и код), их можно удалить в основном, уменьшив код до:

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

Здесь вы дважды проверяете year % 400 и возвращаете true в обоих последних двух случаях:

Это можно упростить до

, и поскольку return выходит из функции, вам не нужен else s:

Вы можете инвертировать эту проверку 1582 для согласованности и меньше вложенности:

Может также инвертировать и объединить их в этой точке:

Одно последнее соображение заключается в том, должна ли функция, называемая isLeapYear() , быть методом всего (кроме класса, представляющего не что иное, как год). Подумайте о том, чтобы сделать его static и принять его year как аргумент.

Возвращение раннего

Если вы вернетесь раньше, вы можете избежать вложенных операторов if. Он даже очень хорошо вписывается в комментарий, который у вас уже есть:

Дополнительно Упростить, если утверждения

Вы также можете сохранить комментарии и if-предложение, если вы сохраните условия в переменных:

При этом ваш код может выглядеть так:

isLeapYearCentury не требуется, я просто оставил его для ясности.

Вы также можете упростить его:

Переменные, конечно, не нужны, но я думаю, что с ними читается намного приятнее.

Разное

  • Ваш длинный комментарий в конце, вероятно, должен быть перенесен в начало.
  • общий стиль Java: открытие фигурных скобок идет по одной строке, if сопровождается пробелом и else идет по той же строке, что и закрывающая фигурная скобка (вам не обязательно следовать соглашениям, но я бы рекомендовал сделать это).

Функция, чтобы проверить, является ли год високосным годом или нет, должен быть методом и взять год в качестве параметра, например, как часть DateUtils класс:

Если вы хотите быть sure , он действительно работает, я рекомендую добавить некоторые модульные тесты, например:

Как указано в @Mark, у вас есть неправильное представление о реформе григорианского календаря . Проблема с предыдущим календарем заключалась не в том, что не было високосных лет. Скорее, было слишком много високосных лет, так что сезоны скользили против календаря на ¾ день в столетие. Решение Папы Грегори заключалось в том, чтобы отменить високосные дни, которые в противном случае имели бы место в 1700, 1800, 1900, 2100 и т. Д.

Я предлагаю написать код таким образом:

Вы также можете написать целую функцию как одно большое логическое выражение, но я не думаю, что это улучшило бы читаемость.

Високосные годы

Надеюсь, вы отлично встретили новый год, и сейчас у вас отличное праздничное настроение. По крайней мере у меня это именно так — мы не пили никакого алкоголя, и чокнулись в полночь бокалами с водой из пятилитровой канистры, поэтому мы проснулись, погуляли, и тут я вспомнил одно из вчерашних поздравлений с Новым годом:

Желаю, чтобы в конце каждого года ты, вспоминая то, что было за последние 366 if ((year%4 == 0 and year%100 != 0) or (year%400 == 0)) else 365 дней, думал про себя:

— Ох, нифига себе, какой был экшен. Обязательно буду рассказывать внукам или напишу об этом потом книгу.

Читать еще:  Как написать игру на javascript

Итак, выше достаточно простой inline-способ определить количество дней в году (переменная year), который, по сути, полностью раскрывает их суть: в григорианском календаре високосными годами считаются те годы, порядковый номер которых либо кратен 4, но при этом не кратен 100, либо кратен 400. Иными словами, если год делится на 4 без остатка, но делится на 100 только с остатком, то он високосный, иначе — невисокосный, кроме случая, если он делится без остатка на 400 — тогда он всё равно високосный.

Например, 2013 год невисокосный, 1700, 1800 и 1900 — опять же невисокосные годы, а вот 2000, 2004, 2008 и 2012 — високосные.

Но что, если мы не помним, сколько дней в високосных (366 дней) и невисокосных (365 дней) годах, или просто хотим написать определение количества дней в году максимально быстро? Можно ли сделать так на Python? Конечно же, можно.

Итак, в Python есть модуль calendar. Он как раз отлично подходит для того, чтобы узнать, является ли тот или иной год високосным (или, например, сколько високосных годов в определённом интервале), определить количество дней в месяце, получить номер дня недели для определённой даты и так далее.

В частности, мы можем получить количество дней в каждом месяце года, и просто сложить.

Функция calendar.monthrange принимает номер года в качестве первого аргумента и номер месяца в качестве второго аргумента. Возвращает номер дня недели первого числа данного месяца и количество дней в данном месяце:

Соответственно, мы можем подсчитать общее количество дней для всех 12 месяцев, и получить таким образом количество дней для данного года:

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

Проверяем с помощью модуля timeit.

На то, чтобы выполнить её 1 миллион раз, требуется 13.69 секунд, если import calendar делается один раз в начале. Если import calendar делается каждый раз, тогда 14.49 секунд.

Теперь попробуем другой вариант. Он требует знания того, сколько дней в високосных и невисокосных годах, но зато он очень короткий:

И, как легко догадаться, он уже намного быстрее: 0.83 секунд, включая import calendar, и 0.26 секунд, если import calendar делается один раз в начале.

Давайте также посмотрим, сколько требуется времени самому первому варианту, с «ручным» подходом: 0.07 секунд для 2012 и 2013 и 0.12 секунд для 2000 (думаю, всем понятно, откуда берётся такая разница в скорости для этих годов).

Получается, что это и есть самый быстрый вариант из этих трёх:

Конечно, в большинстве случаев вы можете использовать любой из этих вариантов — в конце концов, при определении количества дней в одном, двух, десяти или ста годах вы вряд ли почувствуете какую-либо разницу.

Пишите, оптимизируйте, улучшайте, тестируйте и считайте производительность — но не забывайте о читаемости исходников ваших программ.

С Новым годом! Удачи, счастья, радости и самосовершенствования в новом году.

Ссылка на основную публикацию
Adblock
detector