Алгоритм определения високосного года

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

    Год високосный, если он делится на четыре без остатка, но если он делится на 100 без остатка, это не високосный год. Однако, если он делится без остатка на 400, это високосный год. Таким образом, 2000 г. является особым високосным годом, который бывает лишь раз в 400 лет.

Определить, является ли год, который ввел пользователем, високосным или невисокосным.

Високосные года делятся нацело на 4. Однако из этого правила есть исключение: столетия, которые не делятся нацело на 400, високосными не являются.

В високосном годе 366 дней, в обычном 365.

  1. Если год не делится на 4, значит он обычный.
  2. Иначе надо проверить не делится ли год на 100.
  3. Если не делится, значит это не столетие и можно сделать вывод, что год високосный.
  4. Если делится на 100, значит это столетие и его следует проверить его делимость на 400.
  5. Если год делится на 400, то он високосный.
  6. Иначе год обычный.

Проверки можно проводить последовательно, а можно группировать через логические операторы "И" и "ИЛИ". Поэтому способов решения задачи может быть несколько.

var y : word ;
begin
readln ( y ) ;
if y mod 4 <> 0 then writeln ( ‘Обычный’ )
else
if y mod 100 = 0 then
if y mod 400 = 0 then writeln ( ‘Високосный’ )
else writeln ( ‘Обычный’ )
else writeln ( ‘Високосный’ ) ;
end .

var y : word ;
begin
readln ( y ) ;
if ( y mod 4 <> 0 ) or ( y mod 100 = 0 ) and ( y mod 400 <> 0 ) then
writeln ( ‘Обычный’ )
else
writeln ( ‘Високосный’ ) ;
end .

Читайте также:  Php выгрузка в csv

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

Желаю, чтобы в конце каждого года ты, вспоминая то, что было за последние 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. Он как раз отлично подходит для того, чтобы узнать, является ли тот или иной год високосным (или, например, сколько високосных годов в определённом интервале), определить количество дней в месяце, получить номер дня недели для определённой даты и так далее.

Читайте также:  Cool reader не видит книги

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

Функция 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 (думаю, всем понятно, откуда берётся такая разница в скорости для этих годов).

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

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

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

Читайте также:  Hp 3380 драйвер windows 7

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

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *