Почему, чтобы найти високосные годы, год должен быть неделим на 100 и делиться на 400?
Я понимаю, почему он должен делиться на 4. Пожалуйста, объясните алгоритм.
Почему, чтобы найти високосные годы, год должен быть неделим на 100 и делиться на 400?
Я понимаю, почему он должен делиться на 4. Пожалуйста, объясните алгоритм.
Продолжительность года составляет (примерно) 365,242196 дней. Таким образом, мы должны вычесть более или менее четверть дня, чтобы оно соответствовало:
365,242196 - 0,25 = 364,992196 (добавив 1 день за 4 года): но ой, теперь это слишком мало !! давайте добавим сотню суток (не добавляя этот день раз в сто лет :-))
364.992196 + 0,01 = 365.002196 (ой, многовато, давайте все равно добавим этот день примерно раз в 400 лет)
365.002196 - 1/400 = 364.999696
Почти готово, просто поиграйте с високосными секундами время от времени, и все готово.
(Примечание: причина, по которой после этого шага больше не применяются исправления, заключается в том, что год также ИЗМЕНЯЕТСЯ В ДЛИНЕ !!, поэтому високосные секунды являются наиболее гибким решением, см., Например, здесь)
Вот почему я думаю
В 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
На странице википедии о високосных годах есть много информации по этой теме, включая информацию о различных календарях. .
В общих чертах алгоритм расчета високосного года выглядит следующим образом ...
Год будет високосным, если он делится на 4, но не на 100. Если год делится на 4 и на 100, это не високосный год, если он не делится на 400.
Таким образом, такие годы, как 1996, 1992, 1988 и так далее, являются високосными, потому что они делятся на 4, а не на 100. Для столетних лет важно правило 400. Таким образом, столетние 1900, 1800 и 1700 годы, хотя все они все еще делятся на 4, также точно делятся на 100. Поскольку они не делятся на 400, они не являются високосными годами.
этого достаточно, чтобы проверить, является ли год високосным.
if( (year%400==0 || year%100!=0) &&(year%4==0))
cout<<"It is a leap year";
else
cout<<"It is not a leap year";
а) Год - 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 лет). < / сильный>
Я уверен, что Википедия может объяснить это лучше, чем я, но в основном это связано с Тот факт, что если вы добавляете дополнительный день каждые четыре года, мы опережаем Солнце, так как время его обращения вокруг Солнца составляет менее 365,25 дней, поэтому мы компенсируем это, не добавляя високосные дни к годам, которые не делятся на 400, например 1900 г.
надеюсь, это поможет
Вот простая реализация алгоритма википедии с использованием тернарного оператора javascript:
isLeapYear = (year % 100 === 0) ? (year % 400 === 0) : (year % 4 === 0);
if
. Вы заставляете проводить два сравнения в каждом случае, даже если одного будет достаточно. Вычисления, выполняемые на нормально распределенном наборе данных, не пройдут % 4
тест в 75% случаев, поэтому вы должны сделать это в первую очередь и немедленно отказаться от проверки, если это неверно.
- person Anthony; 13.02.2019
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;
Вам действительно стоит сначала попробовать гуглить.
В Википедии есть объяснение високосных лет. алгоритм, который вы описываете, предназначен для Пролептический григорианский календарь.
Более подробную информацию о математике вокруг этого можно найти в статье Календарные алгоритмы.
Не будет ли лучше, если мы сделаем еще один шаг. Если предположить, что каждые 3200 лет - это невисокосный год, длина года наступит.
364.999696 + 1/3200 = 364.999696 + .0003125 = 365.0000085
и после этого корректировка потребуется примерно через 120000 лет.
В 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;
}
PHP:
// is number of days in the year 366? (php days of year is 0 based)
return ((int)date('z', strtotime('Dec 31')) === 365);
Високосные годы произвольны, и система, используемая для их описания, построена руками человека. Нет почему.
Я имею в виду, что високосный год мог быть каждые 28 лет, и у нас была бы дополнительная неделя в эти високосные годы ... но власти решили делать это каждые 4 года, чтобы наверстать упущенное.
Это также связано с тем, что Земле требуется 365,25 дня, чтобы обойти вокруг Солнца и т.д. Из-за этого несоответствия они решили отбросить високосные годы, которые делятся на 100.
Если вас интересуют причины этих правил, то это потому, что время, необходимое Земле, чтобы сделать ровно один оборот вокруг Солнца, является длинным неточным десятичным значением. Это не совсем 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).
В настоящее время в году в среднем примерно 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 год - это одно, но планирование на полторы тысячи лет вперед, на мой взгляд, не является необходимым - имейте в виду, что я был неправильно раньше).
Итак, правила в порядке убывания приоритета:
Здесь возникает довольно непонятная идея. Когда каждый год, делимый на 100, получает 365 дней, что делать в это время? В далеком будущем, когда даже годы, разделенные на 400, могут получить 365 дней.
Тогда есть возможность или причина внести поправки в годы, делящиеся на 80. В нормальных годах будет 365 дней, а в годах, делящихся на 400, может получиться 366 дней. Или это безвыходная ситуация.
Вы можете просто проверить, делится ли число года на 4 и 400. Вам действительно не нужно проверять, неделимо ли оно на 100. Причина, по которой 400 ставится под сомнение, заключается в том, что, согласно григорианскому календарю, наша «продолжительность дня» немного меньше выкл, и, таким образом, чтобы компенсировать это, у нас есть 303 обычных года (по 365 дней каждый) и 97 високосных лет (по 366 дней каждый). Разница между этими 3 дополнительными годами, которые не являются високосными, состоит в том, чтобы оставаться в цикле с григорианским календарем, который повторяется каждые 400 лет. Посмотрите уравнение сравнения Кристиана Зеллера. Это поможет понять настоящую причину. Надеюсь это поможет :)
В григорианском календаре необходимо учитывать 3 критерия для определения високосных лет:
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))
Просто потому, что 2000 год является високосным, и он делится на 100 и делится на 4. Итак, чтобы гарантировать правильный скачок, нам нужно убедиться, что он делится на 400. 2000% 4 = 0 2000% 100 = 0 Согласно алгоритму это не прыжок, но делится на 400 2000% 400 = 0, так что это прыжок.
Я нашел эту проблему в книге «Иллюстрированное руководство по 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
Думаю, это наиболее эффективный способ.
Python:
def leap(n):
if n % 100 == 0:
n = n / 100
return n % 4 == 0
Реализация на C #
public bool LeapYear()
{
int year = 2016;
return year % 4 == 0 && year % 100 != 0 || year % 400 == 0 ;
}
С 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
В оболочке вы можете использовать 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
$
BIS будет 1, если год високосный, иначе 0 в этой логической логике:
BIS = A MOD 4=0 - (A MOD 100=0 AND A>1600) + (A MOD 400=0 AND A>1600)
просто написал это в 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, которую я пишу, потому что написание правильного кода для работы с датами быстро становится неожиданным, поэтому я буду поддерживать только грегорианский календарь (или получу деньги за другой).