Расчет високосного года

Почему, чтобы найти високосные годы, год должен быть неделим на 100 и делиться на 400?

Я понимаю, почему он должен делиться на 4. Пожалуйста, объясните алгоритм.


person Community    schedule 07.04.2009    source источник
comment
Как бы то ни было, календарные вычисления на удивление сложны, особенно если вам нужно ввести дополнительные секунды. Если вы создаете библиотеку, подумайте о ее приобретении. Удачи! :)   -  person Greg D    schedule 07.04.2009
comment
Это не алгоритм, это астрономические факты, адаптированные к человеческой детализации ...   -  person PhiLho    schedule 07.04.2009
comment
https://www.mathsisfun.com/leap-years.html дает четкое объяснение.   -  person Nan Xiao    schedule 28.10.2017
comment
Я голосую за то, чтобы закрыть этот вопрос как не по теме, потому что он не имеет ничего общего с программированием.   -  person BJ Myers    schedule 07.03.2018
comment
Чего стоит, никто не упомянул об этом, что, если год делится на 4000, это НЕ високосный год. Таким образом, 4000, 8000, 12000 и т. Д. Не являются високосными годами.   -  person Yannis Dran    schedule 28.10.2018


Ответы (27)


Продолжительность года составляет (примерно) 365,242196 дней. Таким образом, мы должны вычесть более или менее четверть дня, чтобы оно соответствовало:

365,242196 - 0,25 = 364,992196 (добавив 1 день за 4 года): но ой, теперь это слишком мало !! давайте добавим сотню суток (не добавляя этот день раз в сто лет :-))

364.992196 + 0,01 = 365.002196 (ой, многовато, давайте все равно добавим этот день примерно раз в 400 лет)

365.002196 - 1/400 = 364.999696

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

(Примечание: причина, по которой после этого шага больше не применяются исправления, заключается в том, что год также ИЗМЕНЯЕТСЯ В ДЛИНЕ !!, поэтому високосные секунды являются наиболее гибким решением, см., Например, здесь)

Вот почему я думаю

person Peter    schedule 07.04.2009
comment
Возможно, вы захотите упомянуть, что небольшие различия действительно имеют значение, поскольку в старом юлианском календаре этих поправок не было, и к 16 веку в календаре было более 10 дней выходных для астрономических событий, таких как солнцестояние и (что более важно) дата Пасхи. - person Michael Borgwardt; 14.04.2009
comment
Интересно, что первоначальным источником нынешней системы расчета високосных лет является документ под названием Inter gravissimas, выпущенный папой Григорием XIII в 1582 году. - person Nick Moore; 02.03.2010
comment
Високосные секунды не связаны с вопросом: день не длится ровно 24 часа, и без них полдень по прошествии длительного времени оказался бы посреди ночи. (Принимая во внимание, что високосные годы исправляют проблему, заключающуюся в том, что годы - это не совсем 365 дней, и без поправки декабрь был бы летом в Северном полушарии.) - person Hans Olsson; 04.10.2019

В wikipedia есть алгоритм для определения високосных лет:

function isLeapYear (year):
    if ((year modulo 4 is 0) and (year modulo 100 is not 0))
    or (year modulo 400 is 0)
        then true
    else false

На странице википедии о високосных годах есть много информации по этой теме, включая информацию о различных календарях. .

person Georg Schölly    schedule 07.04.2009
comment
Я только что проверил это, и он правильно определяет високосные и невисокосные годы 1900-2200 из списка високосных лет на kalender-365.de/leap-years.php. - person GlenPeterson; 16.06.2014
comment
Большое спасибо за этот алгоритм. Работает отлично! - person nuccio; 09.03.2017
comment
@Kevin Я не согласен. Вы, кажется, спорите о деталях алгоритма, которые, на мой взгляд, не так уж и важны. По крайней мере, он предоставляет много полезной информации о других календарях и т. Д. - person Georg Schölly; 10.12.2018
comment
@ GeorgSchölly Я понимаю вашу точку зрения ... Я имел в виду ужасный программный ресурс. Алгоритм, опубликованный в Википедии, не проверен и может быть изменен, а иногда и совершенно неверен. Я считаю, что детали алгоритма чрезвычайно важны. Ошибки високосного года вывели из строя множество систем и стоили миллионы и миллионы долларов. (en.wikipedia.org/wiki/Leap_year_bug) Да, я только что процитировал Википедию, не ... т я? Ха! ха! В любом случае код високосного года редко тестируется, и ошибки даты / времени могут иметь разрушительные последствия для системы. Я фанат подробностей. Ваше здоровье! - person Kevin P. Rice; 10.12.2018
comment
И при рассмотрении ошибок високосного года вы должны учитывать не только алгоритм високосного года. Например, программа чтения новостей trn в 1990-е имела ошибку високосного года - она ​​правильно указывала год, но добавляла день в начале года. - person Hans Olsson; 04.10.2019

В общих чертах алгоритм расчета високосного года выглядит следующим образом ...

Год будет високосным, если он делится на 4, но не на 100. Если год делится на 4 и на 100, это не високосный год, если он не делится на 400.

Таким образом, такие годы, как 1996, 1992, 1988 и так далее, являются високосными, потому что они делятся на 4, а не на 100. Для столетних лет важно правило 400. Таким образом, столетние 1900, 1800 и 1700 годы, хотя все они все еще делятся на 4, также точно делятся на 100. Поскольку они не делятся на 400, они не являются високосными годами.

person Ivan Prodanov    schedule 07.04.2009

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

if( (year%400==0 || year%100!=0) &&(year%4==0))
    cout<<"It is a leap year";
else
    cout<<"It is not a leap year";
person prashantitis    schedule 30.08.2014

а) Год - 365,242199 дней.

б) Если бы в году было 365 дней, за 100 лет мы потеряли бы 24,2199 дней. Вот почему мы добавляем 24 дня за столетие (каждые 4 года, ЗА ИСКЛЮЧЕНИЕМ случая, когда он делится на 100)

в) Но все равно мы теряем 0,21299 дня / столетие. Итак, за 4 века мы теряем 0,8796 дней. Вот почему мы добавляем 1 день на 4 века (каждый четвертый век мы ДЕЙСТВИТЕЛЬНО считаем високосным).

г) Но это означает, что мы теряем -0,1204 дня (идем вперед) за четырехсотлетие (4 века). Итак, в 8-м четырехсотлетии (3200 лет) мы НЕ СЧИТАЕМ високосный год.

д) Но это означает, что мы теряем 0,0368 дня за 3200 лет. Таким образом, за 24x3200 лет (= 76800 лет) мы теряем 0,8832 дня. Вот почему мы ДЕЙСТВИТЕЛЬНО считаем високосный год.

и так далее ... (к тому времени мы уже уничтожим планету, так что это не имеет значения)

Я не могу понять, почему мы не считаем високосный год каждые 500 лет вместо 400. Таким образом мы быстрее сходимся к правильному времени (мы потеряем 2,3 часа / 500 лет). < / сильный>

person Theodore Zographos    schedule 09.08.2015

Я уверен, что Википедия может объяснить это лучше, чем я, но в основном это связано с Тот факт, что если вы добавляете дополнительный день каждые четыре года, мы опережаем Солнце, так как время его обращения вокруг Солнца составляет менее 365,25 дней, поэтому мы компенсируем это, не добавляя високосные дни к годам, которые не делятся на 400, например 1900 г.

надеюсь, это поможет

person chillysapien    schedule 07.04.2009

Вот простая реализация алгоритма википедии с использованием тернарного оператора javascript:

isLeapYear = (year % 100 === 0) ? (year % 400 === 0) : (year % 4 === 0);
person Brad    schedule 18.10.2016
comment
Это менее эффективно, чем инструкция if. Вы заставляете проводить два сравнения в каждом случае, даже если одного будет достаточно. Вычисления, выполняемые на нормально распределенном наборе данных, не пройдут % 4 тест в 75% случаев, поэтому вы должны сделать это в первую очередь и немедленно отказаться от проверки, если это неверно. - person Anthony; 13.02.2019
comment
var isleap = !(year%4) && (!!(year%100) || !(year%400)); или, если хотите: var isleap = year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0); - person Quinn Dirks; 16.03.2019

Вернуть true, если входной год високосный.

Базовый современный код:

  If year mod 4 = 0, then leap year
  if year mod 100 then normal year
  if year mod 400 then leap year
  else normal year

Сегодняшнее правило началось в 1582 году нашей эры. Правило юлианского календаря с каждым 4-м годом начиналось с 46 года до н.э., но не является согласованным до 10 года нашей эры, как было заявлено Сезаром. Однако они добавляли несколько високосных лет каждый 3-й год, время от времени в предыдущие годы: таким образом, високосные годы были 45 г. до н.э., 42 г. до н.э., 39 г. до н.э., 36 г. до н.э., 33 г. до н.э., 30 г. до н.э., 27 г. до н. До н.э., 15 г. до н.э., 12 г. до н.э., 9 г. до н.э., 8 г. н.э., 12 г. н.э. До 45 г. до н.э. високосный год не добавлялся.

Год 0 не существует как таковой ... 2BC 1BC 1AD 2AD ... для некоторых вычислений это может быть проблемой.

function isLeapYear(year: Integer): Boolean;
begin
  result := false;
  if year > 1582 then // Todays calendar rule was started in year 1582 
    result := ((year mod 4 = 0) and (not(year mod 100 = 0))) or (year mod 400 = 0)
  else if year > 10 then // Between year 10 and year 1582 every 4th year was a leap year 
    result := year mod 4 = 0
  else //Between year -45 and year 10 only certain years was leap year, every 3rd year but the entire time
    case year of
      -45, -42, -39, -36, -33, -30, -27, -24, -21, -18, -15, -12, -9:
        result := true;
    end;
end;
person Eskil Mjelva Saatvedt    schedule 12.03.2014

Вам действительно стоит сначала попробовать гуглить.

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

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

person Davy Landman    schedule 07.04.2009
comment
Кстати, похоже, что разработчики Google слишком круты, чтобы читать Википедию: github.com/android/platform_frameworks_base/blob/ и результат: code.google.com/p/android/issues/detail?id=200371 :) - person JustAMartin; 10.03.2017
comment
Небольшой поворот в том, что этот пост сейчас занимает довольно высокое место в поисковом рейтинге Google, ха-ха. - person hiljusti; 26.09.2017

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

364.999696 + 1/3200 = 364.999696 + .0003125 = 365.0000085

и после этого корректировка потребуется примерно через 120000 лет.

person Sandeep Agrawal    schedule 28.12.2011
comment
Сандип Агравал, снова Небольшая модификация в моем предложении выше: - Вместо 3000 возьмите 3200 лет как невисокосный (потому что 3000 сам по себе не високосный год, так как он не делится на 400). високосный год расчет будет следующим: - 364,999696 +1/3200 = 364,999696 + .0003125 = 365,0000085, и теперь вряд ли потребуется дальнейшая корректировка. (примерно через 12000 лет) - person Sandeep Agrawal; 28.12.2011
comment
через 12000 лет (принимая 12000 за невисокосный год) расчет будет: - - person Sandeep Agrawal; 28.12.2011

В Java код ниже рассчитывает количество високосных лет между двумя заданными годами. Определите начальную и конечную точки петли.

Тогда, если параметр по модулю 4 равен 0, а параметр по модулю 100 не равен 0 или параметр по модулю 400 равен нулю, то это високосный год и счетчик увеличения.

static int calculateLeapYearCount(int year, int startingYear) {
        int min = Math.min(year, startingYear);
        int max = Math.max(year, startingYear);
        int counter = 0;
        for (int i = min; i < max; i++) {
            if ((i % 4 == 0 && i % 100 != 0) || i % 400 == 0) {
                counter = counter + 1;
            }
        }
        return counter;
    }
person erhun    schedule 07.01.2017

PHP:

// is number of days in the year 366?  (php days of year is 0 based)
return ((int)date('z', strtotime('Dec 31')) === 365);
person self.name    schedule 04.03.2017
comment
дата ('L') более эффективна - person Book Of Zeus; 05.03.2017

Високосные годы произвольны, и система, используемая для их описания, построена руками человека. Нет почему.

Я имею в виду, что високосный год мог быть каждые 28 лет, и у нас была бы дополнительная неделя в эти високосные годы ... но власти решили делать это каждые 4 года, чтобы наверстать упущенное.

Это также связано с тем, что Земле требуется 365,25 дня, чтобы обойти вокруг Солнца и т.д. Из-за этого несоответствия они решили отбросить високосные годы, которые делятся на 100.

person inspite    schedule 07.04.2009

Если вас интересуют причины этих правил, то это потому, что время, необходимое Земле, чтобы сделать ровно один оборот вокруг Солнца, является длинным неточным десятичным значением. Это не совсем 365,25. Это немного меньше 365,25, поэтому каждые 100 лет необходимо исключать один високосный день (365,25 - 0,01 = 365,24). Но это тоже не совсем так. Значение немного больше 365,24. Таким образом, только 3 раза из 4 будет применяться правило 100 лет (или, другими словами, прибавлять через 1 день каждые 400 лет; 365,25 - 0,01 + 0,0025 = 365,2425).

person BlueMonkMN    schedule 07.04.2009

В настоящее время в году в среднем примерно 365,2425 дней (Земля замедляется, но пока давайте проигнорируем это).

Причина, по которой у нас високосные годы каждые 4 года, заключается в том, что в результате мы получаем в среднем 365,25 [(365+365+365+366) / 4 = 365.25, 1461 days in 4 years].

Причина, по которой у нас нет високосных лет для 100-кратных, состоит в том, чтобы довести нас до 365,24 `[(1461 x 25 - 1) / 100 = 365,24, 36 524 дня за 100 лет.

Тогда причина, по которой у нас снова високосный год на 400-кратные, состоит в том, чтобы довести нас до 365,2425 [(36,524 x 4 + 1) / 400 = 365.2425, 146,097 days in 400 years].

Я считаю, что может быть другое правило для кратных 3600, но я никогда не кодировал его (2000 год - это одно, но планирование на полторы тысячи лет вперед, на мой взгляд, не является необходимым - имейте в виду, что я был неправильно раньше).

Итак, правила в порядке убывания приоритета:

  • кратное 400 - високосный год.
  • кратное 100 - не високосный год.
  • кратное 4 - високосный год.
  • все остальное - не високосный год.
person paxdiablo    schedule 07.04.2009

Здесь возникает довольно непонятная идея. Когда каждый год, делимый на 100, получает 365 дней, что делать в это время? В далеком будущем, когда даже годы, разделенные на 400, могут получить 365 дней.

Тогда есть возможность или причина внести поправки в годы, делящиеся на 80. В нормальных годах будет 365 дней, а в годах, делящихся на 400, может получиться 366 дней. Или это безвыходная ситуация.

person Finn Jensen    schedule 22.04.2013
comment
Следующий раз, когда год делится на 400, будет в 2400 году. И нас просто не волнует, что произойдет if и когда мы доберемся туда. - person Bo Persson; 22.04.2013

Вы можете просто проверить, делится ли число года на 4 и 400. Вам действительно не нужно проверять, неделимо ли оно на 100. Причина, по которой 400 ставится под сомнение, заключается в том, что, согласно григорианскому календарю, наша «продолжительность дня» немного меньше выкл, и, таким образом, чтобы компенсировать это, у нас есть 303 обычных года (по 365 дней каждый) и 97 високосных лет (по 366 дней каждый). Разница между этими 3 дополнительными годами, которые не являются високосными, состоит в том, чтобы оставаться в цикле с григорианским календарем, который повторяется каждые 400 лет. Посмотрите уравнение сравнения Кристиана Зеллера. Это поможет понять настоящую причину. Надеюсь это поможет :)

person Balaji    schedule 01.05.2014

В григорианском календаре необходимо учитывать 3 критерия для определения високосных лет:

  1. Год делится на 4 без остатка;
  2. Если год можно равномерно разделить на 100, это НЕ високосный год, если только;
  3. Год также делится на 400 без остатка. Тогда это високосный год. Почему год, разделенный на 100, не является високосным
person Milon    schedule 26.11.2014

Python 3.5

def is_leap_baby(year):
    if ((year % 4 is 0) and (year % 100 is not 0)) or (year % 400 is 0):
        return "{0}, {1} is a leap year".format(True, year)
    return "{0} is not a leap year".format(year)

print(is_leap_baby(2014))
print(is_leap_baby(2012))
person Samuel    schedule 25.12.2016

Просто потому, что 2000 год является високосным, и он делится на 100 и делится на 4. Итак, чтобы гарантировать правильный скачок, нам нужно убедиться, что он делится на 400. 2000% 4 = 0 2000% 100 = 0 Согласно алгоритму это не прыжок, но делится на 400 2000% 400 = 0, так что это прыжок.

person ahmed    schedule 19.10.2018

Я нашел эту проблему в книге «Иллюстрированное руководство по Python 3». Это было в очень ранней главе, в которой обсуждались только математические операции, без циклов, без сравнений, без условных выражений. Как узнать, является ли данный год високосным?

Вот что я придумал:

y = y % 400
a = y % 4
b = y % 100
c = y // 100
ly = (0**a) * ((1-(0**b)) + 0**c)   # ly is not zero for leap years, else 0
person darthwarden    schedule 26.12.2018

Думаю, это наиболее эффективный способ.

Python:

def leap(n):
    if n % 100 == 0:
        n = n / 100
    return n % 4 == 0
person Mikha'el Wade    schedule 06.03.2019

Реализация на C #

public bool LeapYear()
{
     int year = 2016;

     return year % 4 == 0 && year % 100 != 0 || year % 400 == 0 ;
}
person Etnic    schedule 26.05.2019

С 1700 по 1917 год официальным календарем был юлианский календарь. С тех пор мы используем систему григорианского календаря. Переход от юлианского календаря к григорианскому календарю произошел в 1918 году, когда на следующий день после 31 января было 14 февраля. Это означает, что 32-й день 1918 года был 14 февраля.

В обеих календарных системах февраль - единственный месяц с переменным количеством дней, в нем 29 дней в високосном году и 28 дней во все остальные годы. В юлианском календаре високосные годы делятся на 4, а в григорианском календаре високосные годы бывают следующими:

Делится на 400.

Делится на 4 и не делится на 100.

Итак, программа на високосный год будет такой:

Python:

def leap_notleap(year):

    yr = ''
    if year <= 1917:
        if year % 4 == 0:
            yr = 'leap'
        else:
            yr = 'not leap'
    elif year >= 1919:
        if (year % 400 == 0) or (year % 4 == 0 and year % 100 != 0):
            yr = 'leap'
        else:
            yr = 'not leap'
    else:
        yr = 'none actually, since feb had only 14 days'

    return yr
person Sanket Mathur    schedule 29.11.2019

В оболочке вы можете использовать cal -j YYYY, который печатает юлианский день года. Если последний юлианский день равен 366, то это високосный год.

$ function check_leap_year
 {
  year=$1
   if [ `cal -j $year | awk 'NF>0' | awk 'END { print $NF } '` -eq 366 ];
   then
      echo "$year -> Leap Year";
   else
      echo "$year -> Normal Year" ;
   fi
 }
$ check_leap_year 1900
1900 -> Normal Year
$ check_leap_year 2000
2000 -> Leap Year
$ check_leap_year 2001
2001 -> Normal Year
$ check_leap_year 2020
2020 -> Leap Year
$

Используя awk, вы можете сделать

$ awk -v year=1900 ' BEGIN { jul=strftime("%j",mktime(year " 12 31 0 0 0 ")); print jul } '
365
$ awk -v year=2000 ' BEGIN { jul=strftime("%j",mktime(year " 12 31 0 0 0 ")); print jul } '
366
$ awk -v year=2001 ' BEGIN { jul=strftime("%j",mktime(year " 12 31 0 0 0 ")); print jul } '
365
$ awk -v year=2020 ' BEGIN { jul=strftime("%j",mktime(year " 12 31 0 0 0 ")); print jul } '
366
$
person stack0114106    schedule 16.05.2020

BIS будет 1, если год високосный, иначе 0 в этой логической логике:

BIS = A MOD 4=0 - (A MOD 100=0 AND A>1600) + (A MOD 400=0 AND A>1600)
person Gipelle    schedule 13.06.2021

просто написал это в Coffee-Script:

is_leap_year = ( year ) ->
  assert isa_integer year
  return true   if year % 400 == 0
  return false  if year % 100 == 0
  return true   if year %   4 == 0
  return false

# parseInt? that's not even a word. 
# Let's rewrite that using real language:
integer = parseInt 

isa_number = ( x ) ->
  return Object.prototype.toString.call( x ) == '[object Number]' and not isNaN( x )

isa_integer = ( x ) ->
  return ( isa_number x ) and ( x == integer( x ) )

Конечно, проверка достоверности, сделанная здесь, идет немного дальше того, о чем просили, но я считаю, что это необходимо при хорошем программировании.

обратите внимание, что возвращаемые значения этой функции указывают високосные годы в так называемом пролептическом грегорианском календаре, поэтому для 1400 года он указывает false, тогда как на самом деле этот год был високосным, согласно тогдашнему -используемый юлианский календарь. Я все равно оставлю его как таковой в библиотеке datetime, которую я пишу, потому что написание правильного кода для работы с датами быстро становится неожиданным, поэтому я буду поддерживать только грегорианский календарь (или получу деньги за другой).

person flow    schedule 21.08.2011