Алгоритм расчета дня недели
Сравнение Целлера — это алгоритм , разработанный Кристианом Целлером в 19 веке для расчета дня недели для любой даты по юлианскому или григорианскому календарю . Можно считать, что он основан на преобразовании юлианского дня в календарную дату.
Формула
Для григорианского календаря сравнение Целлера равно
![{\displaystyle h=\left(q+\left\lfloor {\frac {13(m+1)}{5}}\right\rfloor +K+\left\lfloor {\frac {K}{4}}\right \rfloor +\left\lfloor {\frac {J}{4}}\right\rfloor -2J\right){\bmod {7}},}](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)
для юлианского календаря это
![{\displaystyle h=\left(q+\left\lfloor {\frac {13(m+1)}{5}}\right\rfloor +K+\left\lfloor {\frac {K}{4}}\right \rfloor +5-J\right){\bmod {7}},}](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)
где
- h — день недели (0 = суббота, 1 = воскресенье, 2 = понедельник, ..., 6 = пятница)
- q — день месяца
- m — месяц (3 = март, 4 = апрель, 5 = май, ..., 14 = февраль)
- К год века ( ).
![{\displaystyle год{\bmod {1}}00}](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)
- J — столетие , отсчитываемое от нуля (на самом деле ). Например, столетия, отсчитываемые от нуля для 1995 и 2000 годов, равны 19 и 20 соответственно (не путать с обычным порядковым перечислением веков, которое в обоих случаях указывает 20-е).
![{\displaystyle \lflooryear/100\rfloor}](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)
это функция пола или целая часть- mod — операция по модулю или остаток после деления
В этом алгоритме январь и февраль считаются 13 и 14 месяцами предыдущего года. Например, если это 2 февраля 2010 г., алгоритм считает дату вторым днем четырнадцатого месяца 2009 г. (14 февраля 2009 г. в формате ДД/ММ/ГГГГ).
Для даты недели ISO «День недели d» (от 1 = понедельник до 7 = воскресенье) используйте
![{\displaystyle d=((h+5){\bmod {7}})+1}](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)
Анализ
Эти формулы основаны на наблюдении, что день недели развивается предсказуемым образом на основе каждой части этой даты. Каждый член формулы используется для расчета смещения, необходимого для получения правильного дня недели.
Таким образом, для григорианского календаря различные части этой формулы можно понимать следующим образом:
представляет прогрессию дня недели на основе дня месяца, поскольку каждый последующий день приводит к дополнительному смещению дня недели на 1.
представляет последовательность дней недели в зависимости от года. Предполагая, что длина каждого года составляет 365 дней, одна и та же дата каждого последующего года будет компенсироваться значением .![{\displaystyle 365{\bmod {7}}=1}](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)
- Поскольку в каждом високосном году 366 дней, это необходимо учитывать, добавляя еще один день к значению смещения дня недели. Это достигается путем добавления к смещению. Этот термин рассчитывается как целочисленный результат. Любой остаток отбрасывается.
![{\displaystyle \left\lfloor {\frac {K}{4}}\right\rfloor }](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)
- Используя аналогичную логику, прогресс дня недели для каждого столетия можно вычислить, заметив, что в обычном столетии 36 524 дня, а в каждом столетии 36 525 дней, делящихся на 400. Поскольку и , этот термин объясняет это.
![{\displaystyle 36525{\bmod {7}}=6}](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)
![{\displaystyle 36524{\bmod {7}}=5}](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)
![{\displaystyle \left\lfloor {\frac {J}{4}}\right\rfloor -2J}](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)
- Срок корректируется с учетом изменения дней месяца. С января дни в месяце {31, 28/29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}. 28 или 29 дней в феврале — это проблема, поэтому формула переносит январь и февраль до конца, поэтому короткий подсчет февраля не вызовет проблем. Формула интересует дни недели, поэтому числа в последовательности можно брать по модулю 7. Тогда количество дней в месяце по модулю 7 (все еще начиная с января) будет равно {3, 0/1, 3, 2. , 3, 2, 3, 3, 2, 3, 2, 3}. Начиная с марта, последовательность в основном чередуется 3, 2, 3, 2, 3, но каждые пять месяцев подряд идут два месяца по 31 день (июль-август и декабрь-январь). [1] Дробь 13/5 = 2,6 и функция пола имеют такой эффект; знаменатель 5 устанавливает период в 5 месяцев.
![{\displaystyle \left\lfloor {\frac {13(m+1)}{5}}\right\rfloor }](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)
- Общая функция нормализует результат, чтобы он находился в диапазоне от 0 до 6, что дает индекс правильного дня недели для анализируемой даты.
![{\displaystyle \operatorname {mod} \,7}](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)
Причина, по которой формулы различаются в разных календарях, заключается в том, что в юлианском календаре нет отдельного правила для високосных веков, и он смещен от григорианского календаря на фиксированное количество дней в каждом столетии.
Поскольку григорианский календарь был принят в разное время в разных регионах мира, место события имеет важное значение для определения правильного дня недели для даты, произошедшей в этот переходный период. Это требуется только до 1929 года, поскольку это был последний год, когда юлианский календарь все еще использовался какой-либо страной на земле, и поэтому не требуется для 1930 года или позже.
Формулы можно использовать в упреждающих целях, но «Год 0» на самом деле — это год 1 до н.э. (см. нумерацию астрономических лет ). Юлианский календарь на самом деле является предварительным вплоть до 1 марта 4 г. н. э. из-за плохого управления в Риме (но не в Египте) в период с момента введения календаря в силу 1 января 45 г. до н. э. (который не был високосным годом). Кроме того, оператор по модулю может обрезать целые числа в неправильном направлении (потолок вместо минимума). Чтобы учесть это, можно добавить достаточное количество лет, кратное 400 григорианским или 700 юлианским годам.
Примеры
Для 1 января 2000 г. датой будет считаться 13-й месяц 1999 г., поэтому значения будут следующими:
![{\displaystyle q=1}](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)
![{\displaystyle м=13}](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)
![{\displaystyle K=99}](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)
![{\displaystyle J=19}](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)
Таким образом, формула оценивается как .![{\displaystyle (1+36+99+24+4-38){\bmod {7}}=126{\bmod {7}}=0={\text{суббота}}}](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)
(36 получается из , усеченного до целого числа.)![{\displaystyle (13+1)\times 13/5=182/5}](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)
Однако для 1 марта 2000 г. дата рассматривается как третий месяц 2000 г., поэтому значения становятся
![{\displaystyle q=1}](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)
![{\displaystyle м=3}](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)
![{\displaystyle K=0}](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)
![{\displaystyle J=20}](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)
поэтому формула оценивается как .![{\displaystyle (1+10+0+0+5-40){\bmod {7}}=-24{\bmod {7}}=4={\text{среда}}}](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)
Реализации в программном обеспечении
Базовая модификация
Формулы основаны на математическом определении деления по модулю , что означает, что -2 по модулю 7 равно положительному 5. К сожалению, в большинстве компьютерных языков функция усечения реализуется методом усечения, -2 по модулю 7 возвращает результат -2. Итак, чтобы реализовать сравнение Целлера на компьютере, формулы следует немного изменить, чтобы числитель был положительным. Самый простой способ сделать это — заменить − 2 J на + 5 J и − J на + 6 J .
Для григорианского календаря сравнение Целлера становится
![{\displaystyle h=\left(q+\left\lfloor {\frac {13(m+1)}{5}}\right\rfloor +K+\left\lfloor {\frac {K}{4}}\right \rfloor +\left\lfloor {\frac {J}{4}}\right\rfloor +5J\right){\bmod {7}},}](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)
Для юлианского календаря сравнение Целлера принимает вид
![{\displaystyle h=\left(q+\left\lfloor {\frac {13(m+1)}{5}}\right\rfloor +K+\left\lfloor {\frac {K}{4}}\right \rfloor +5+6J\right){\bmod {7}},}](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)
Легко видеть, что в данном году последний день февраля и 1 марта являются хорошими датами испытаний.
В качестве примечания: если у нас есть трехзначное число abc, где a, b и c — цифры, каждая неположительная, если abc неположительная; у нас есть (abc) mod 7 = 9*a + 3*b + c. Повторите формулу до одной цифры. Если результат 7, 8 или 9, то вычтите 7. Если вместо этого результат отрицательный, то прибавьте 7. Если результат все еще отрицательный, то прибавьте 7 еще раз. Используя этот подход, мы можем избежать беспокойства по поводу языковых различий в оценках mod 7. Это также может улучшить технику мысленной математики.
Общее упрощение
Целлер использовал десятичную арифметику и счел удобным использовать J и K для обозначения года. Но при использовании компьютера проще обрабатывать измененные год Y и месяц m , которые в январе и феврале равны Y - 1 и m + 12 :
Для григорианского календаря сравнение Целлера становится
![{\displaystyle h=\left(q+\left\lfloor {\frac {13(m+1)}{5}}\right\rfloor +Y+\left\lfloor {\frac {Y}{4}}\right \rfloor -\left\lfloor {\frac {Y}{100}}\right\rfloor +\left\lfloor {\frac {Y}{400}}\right\rfloor \right){\bmod {7}} ,}](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)
В этом случае нет возможности опустошения из-за единственного отрицательного члена, потому что .![{\displaystyle \left\lfloor Y/4\right\rfloor \geq \left\lfloor Y/100\right\rfloor }](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)
Для юлианского календаря сравнение Целлера принимает вид
![{\displaystyle h=\left(q+\left\lfloor {\frac {13(m+1)}{5}}\right\rfloor +Y+\left\lfloor {\frac {Y}{4}}\right \rfloor +5\right){\bmod {7}},}](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)
Приведенный выше алгоритм упоминается для григорианского случая в RFC 3339, Приложение B, хотя и в сокращенной форме, которая возвращает 0 для воскресенья.
Другие варианты
По крайней мере, три других алгоритма разделяют общую структуру сравнения Целлера в ее типе «общего упрощения», также используя m ∈ [3, 14] ∩ Z и конструкцию «модифицированного года».
- В 1990 году Майкл Кейт опубликовал фрагмент очень короткого кода на языке C для григорианских дат. Компонент длины месяца ( ) заменяется на . [2]
![{\displaystyle \left\lfloor {\frac {13(m+1)}{5}}\right\rfloor }](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)
![{\displaystyle \left\lfloor {\frac {23m}{9}}\right\rfloor +4}](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)
- Дж. Р. Стоктон предоставляет версию Sunday is-0 с , называя ее вариацией Zeller. [2]
![{\displaystyle \left\lfloor {\frac {13(m-2)}{5}}\right\rfloor +2}](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)
- Клаус Тендеринг описывает его как замену «воскресенье — 0». [3]
![{\displaystyle \left\lfloor {\frac {31(m-2)}{12}}\right\rfloor }](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)
Можно показать, что оба выражения прогрессируют с отклонением на единицу от исходного компонента длины месяца в требуемом диапазоне m , что приводит к начальному значению 0 для воскресенья.
Смотрите также
Рекомендации
- ^ Правило каждые пять месяцев применяется только к двенадцати месяцам года, начиная с 1 марта и заканчивая последним днем следующего февраля.
- ^ Аб Стоктон, младший «Материал, связанный с сравнением Целлера». «Мерлин», из архива NCTU Тайваня .
- ^ Тендеринг, Клаус. «Вопросы недели». www.tondering.dk .
Библиография
Каждая из этих четырех одинаковых газет с изображениями посвящена, во-первых, дню недели, а во-вторых, дате пасхального воскресенья в юлианском и григорианском календарях. Страницы ссылаются на переводы на английский язык.
- Целлер, Кристиан (1882). «Die Grundaufgaben der Kalenderrechnung auf neue und vereinfachte Weise gelöst». Württembergische Vierteljahrshefte für Landesgeschichte (на немецком языке). В : 313–314. Архивировано из оригинала 11 января 2015 года.
- Целлер, Кристиан (1883). «Проблема дуплексного календаря фундаментале». Бюллетень математического общества Франции (на латыни). 11 : 59–61. Архивировано из оригинала 11 января 2015 года.
- Целлер, Кристиан (1885). «Календер-Формельн». Mathematich-naturwissenschaftliche Mitteilungen des mathematich-naturwissenschaftlichen Vereins в Вюртемберге (на немецком языке). 1 (1): 54–58. Архивировано из оригинала 11 января 2015 года.
- Целлер, Кристиан (1886). «Календер-Формельн». Acta Mathematica (на немецком языке). 9 : 131–136. дои : 10.1007/BF02406733 .
Внешние ссылки
- Календарные труды ректора Хр. Зеллер: Формулы дня недели и Пасхи, автор Дж. Р. Стоктон, недалеко от Лондона, Великобритания. На сайте представлены изображения и переводы четырех вышеупомянутых статей, а также справочной карточки Целлера «Das Ganze der Kalender-Rechnung».
Эта статья включает общедоступные материалы Пола Э. Блэка. «Сравнение Целлера». Словарь алгоритмов и структур данных . НИСТ .