Реализации алгоритмов/Алгоритм пасхалии: различия между версиями

Материал из Викиучебника — открытых книг для открытого мира
Содержимое удалено Содержимое добавлено
оформление
Добавлены описание задачи, описание алгоритма и реализации на Basic, C, C++, Go, Pascal, Python, Rust
Строка 1: Строка 1:
{{wikipedia|Пасхалия}}
{{wikipedia|Пасхалия}}
'''Пасха''' (англ. '''Easter''') — христианский праздник воскресения Иисуса Христа, отмечающийся в первое воскресенье после первого полнолуния, наступающего не ранее весеннего равноденствия; таким образом он не привязан к конкретной дате («преходящий праздник»). Под полнолунием и равноденствием понимаются не фактические астрономические явления, а их расчётные даты: полнолуние вычисляется по Метонову циклу, за равноденствие берётся 21 марта (календарное равноденствие для северного полушария).
== [[w:Perl|Perl]] ==

: Rich Bowen’s модуль ''Date::Easter'' доступен на сайте CPAN .<ref>{{cite web|title=Date::Easter|url=http://search.cpan.org/~rbow/Date-Easter-1.14/lib/Date/Easter.pm|publisher=CPAN|archiveurl=http://www.webcitation.org/6FcDSMkSb|archivedate=2013-04-04}}</ref>
'''Пасхалия''' (англ. = лат. '''Computus''' — исчисление) — методика расчёта даты празднования Пасхи в том или ином году. В настоящее время большинство православных церквей используют александрийскую пасхалию, опирающуюся на юлианский календарь («старый стиль»), тогда как католическая, а также некоторые православные и протестантские церкви придерживаются григорианской, основанной на общепринятом григорианском календаре. Из-за расхождения между этими календарями (13 дней на сегодня) разница между датами празднования «католической» и «православной» Пасхи в разные годы может составлять 0, 1, 4 или 5 недель.

==Описание==
Существуют различные алгоритмы пасхалии. Здесь использован алгоритм григорианской пасхалии неизвестного автора (журнал New York correspondent, 1876) и его адаптация бельгийским математиком-астрономом Жаном Меёсом (франц. Jean Meeus) для александрийской пасхалии (Jean Meeus - Astronomical Algorithms, 1991).

'''Дано:''' год

'''Найти:''' месяц, день

Вычисляется фактор. <code>ЦЕЛ(x)</code> означает целую часть выражения, <code>ОСТ(x / y)</code> — остаток от деления.

Александрийская пасхалия:
<syntaxhighlight>
d = ОСТ((ОСТ(год / 19) × 19 + 15) / 30)
factor = d + ОСТ(((ОСТ(год / 4) × 2) + (ОСТ(год / 7) × 4) + 34 − d) / 7) + 114
</syntaxhighlight>

Григорианская пасхалия:
<syntaxhighlight>
a = ОСТ(год / 19)
b = ЦЕЛ(год / 100)
c = ОСТ(год / 100)
h = ОСТ((19 × a + b − ЦЕЛ(b / 4) − ЦЕЛ((b − ЦЕЛ((b + 8) / 25) + 1) / 3) + 15) / 30)
l = ОСТ((32 + (ОСТ(b / 4) + ЦЕЛ(c / 4)) × 2 − h − ОСТ(c / 4)) / 7)
factor = h + l − ЦЕЛ((11 × (h + 2 × l) + a) / 451) × 7 + 114
</syntaxhighlight>

Месяц и день Пасхи вычисляются из фактора:

<syntaxhighlight>
месяц = ЦЕЛ(factor / 31)
день = ОСТ(factor / 31) + 1
</syntaxhighlight>

Для григорианской пасхи найденные значения определяют григорианскую дату, а для александрийской — юлианскую.

==Реализации==
===[[w:PowerBASIC|PowerBASIC]], [[w:QBASIC|QBASIC]], [[w:QuickBasic|QuickBasic]] версий 4.X, [[w:Visual Basic|Visual Basic]] версий ≤ 6.0, [[w:Visual Basic for Applications|Visual Basic для приложений]]===
<syntaxhighlight lang="vb">
' computus.bas

' ComputusGetEaster вычисляет по данному фактору месяц и день Пасхи (приватная функция).
Sub ComputusGetEaster(factor As Integer, month As Integer, day As Integer)
month = factor \ 31
day = factor Mod 31 + 1
End Sub

' ComputusGetAlexandrian вычисляет для данного года месяц и день православной Пасхи (юлианская дата).
Sub ComputusGetAlexandrian(year As Integer, month As Integer, day As Integer)
Dim d As Integer
d = (year Mod 19 * 19 + 15) Mod 30
ComputusGetEaster d + (year Mod 4 * 2 + year Mod 7 * 4 + 34 - d) Mod 7 + 114, month, day
End Sub

' ComputusGetGregorian вычисляет для данного года месяц и день католической Пасхи (григорианская дата).
Sub ComputusGetGregorian(year As Integer, month As Integer, day As Integer)
Dim a As Integer, b As Integer, c As Integer, h As Integer, l As Integer
a = year Mod 19
b = year \ 100
c = year Mod 100
h = (19 * a + b - b \ 4 - (b - (b + 8) \ 25 + 1) \ 3 + 15) Mod 30
l = (32 + (b Mod 4 + c \ 4) * 2 - h - c Mod 4) Mod 7
ComputusGetEaster h + l - (11 * (h + l + l) + a) \ 451 * 7 + 114, month, day
End Sub
</syntaxhighlight>
Пример использования:
<syntaxhighlight lang="vb">
' comptest.bas

' PrintDate выводит дату в формате:
' К: ГГГГ-ММ-ДД
' где К — название календаря, ГГГГ — год, ММ — двузначный номер месяца, ДД — двузначное число.
Sub PrintDate(calendar As String, year As Integer, month As Integer, day As Integer)
Print calendar; ": ";
Print year; "-";
If month < 10 Then Print "0";
Print Str(month); "-";
If day < 10 Then Print "0";
Print Str(day)
End Sub

' Для Visual Basic добавить здесь Sub Main

Dim year As Integer

Input "Year", year

Dim month As Integer, day As Integer

ComputusGetAlexandrian year, month, day
PrintDate "Alexandrian", year, month, day

ComputusGetGregorian year, month, day
PrintDate "Gregorian", year, month, day

' Для Visual Basic добавить здесь End Sub
</syntaxhighlight>

===[[w:C|C]]===
<syntaxhighlight lang="c">
/* computus.h */

#ifndef _COMPUTUS_H_
#define _COMPUTUS_H_


typedef unsigned short Year;
typedef unsigned char Month;
typedef unsigned char Day;

/*
computus_get_alexandrian вычисляет для данного года месяц и день православной Пасхи (юлианская дата).
*/
void computus_get_alexandrian(Year year, Month *month, Day *day);

/*
computus_get_gregorian вычисляет для данного года месяц и день католической Пасхи (григорианская дата).
*/
void computus_get_gregorian(Year year, Month *month, Day *day);


#endif


/* computus.c */

#include "computus.h"


/*
_computus_get_easter вычисляет по данному фактору месяц и день Пасхи (приватная функция).
*/
void _computus_get_easter(Year factor, Month *month, Day *day) {
*month = Month(factor / 31);
*day = Day(factor % 31 + 1);
}

void computus_get_alexandrian(Year year, Month *month, Day *day) {
Year d = (year % 19 * 19 + 15) % 30;
_computus_get_easter(d + (year % 4 * 2 + year % 7 * 4 + 34 - d) % 7 + 114, month, day);
}

void computus_get_gregorian(Year year, Month *month, Day *day) {
Year
a = year % 19,
b = year / 100,
c = year % 100,
h = (19 * a + b - b / 4 - (b - (b + 8) / 25 + 1) / 3 + 15) % 30,
l = (32 + (b % 4 + c / 4) * 2 - h - c % 4) % 7;
_computus_get_easter(h + l - (11 * (h + l + l) + a) / 451 * 7 + 114, month, day);
}
</syntaxhighlight>
Пример использования:
<syntaxhighlight lang="c">
/* computus_test.c */

#include <stdio.h>

#include "computus.h"


/*
print_date выводит дату в формате:
К: ГГГГ-ММ-ДД
где К — название календаря, ГГГГ — год, ММ — двузначный номер месяца, ДД — двузначное число.
*/
void print_date(const char *calendar, Year year, Month month, Day day) {
printf("%s: %hu-%.2hu-%.2hu\n", calendar, year, month, day);
}

int main() {
Year year;
printf("Year? ");
scanf("%hu", &year);

Month month;
Day day;

computus_get_alexandrian(year, &month, &day);
print_date("Alexandrian", year, month, day);

computus_get_gregorian(year, &month, &day);
print_date("Gregorian", year, month, day);
}
</syntaxhighlight>

===[[w:C++|C++]]===
<syntaxhighlight lang="cpp">
// computus.hpp

#pragma once


namespace computus {

typedef unsigned short Year;
typedef unsigned char Month;
typedef unsigned char Day;

// getAlexandrian вычисляет для данного года месяц и день православной Пасхи (юлианская дата).
void getAlexandrian(Year year, Month &month, Day &day);

// getGregorian вычисляет для данного года месяц и день католической Пасхи (григорианская дата).
void getGregorian(Year year, Month &month, Day &day);

}


// computus.cpp

#include "computus.hpp"


namespace computus {

// _getEaster вычисляет по данному фактору месяц и день Пасхи (приватная функция).
void _getEaster(Year factor, Month &month, Day &day) {
month = Month(factor / 31);
day = Day(factor % 31 + 1);
}

void getAlexandrian(Year year, Month &month, Day &day) {
Year d = (year % 19 * 19 + 15) % 30;
_getEaster(d + (year % 4 * 2 + year % 7 * 4 + 34 - d) % 7 + 114, month, day);
}
void getGregorian(Year year, Month &month, Day &day) {
Year
a = year % 19,
b = year / 100,
c = year % 100,
h = (19 * a + b - b / 4 - (b - (b + 8) / 25 + 1) / 3 + 15) % 30,
l = (32 + (b % 4 + c / 4) * 2 - h - c % 4) % 7;
_getEaster(h + l - (11 * (h + l + l) + a) / 451 * 7 + 114, month, day);
}

}
</syntaxhighlight>
Пример использования:
<syntaxhighlight lang="cpp">
// computus_test.cpp

#include <iostream>
#include <iomanip>

#include "computus.hpp"


// printDate выводит дату в формате:
// К: ГГГГ-ММ-ДД
// где К — название календаря, ГГГГ — год, ММ — двузначный номер месяца, ДД — двузначное число.
void printDate(const char *calendar, computus::Year year, computus::Month month, computus::Day day) {
std::cout
<< calendar << ':' << ' ' << year
<< '-' << std::setw(2) << std::setfill('0') << int(month)
<< '-' << std::setw(2) << std::setfill('0') << int(day)
<< '\n';
}

int main() {
computus::Year year;
std::cout << "Year? ";
std::cin >> year;

computus::Month month;
computus::Day day;

computus::getAlexandrian(year, month, day);
printDate("Alexandrian", year, month, day);

computus::getGregorian(year, month, day);
printDate("Gregorian", year, month, day);
}
</syntaxhighlight>


== [[w:Excel|Excel]] ==
===[[w:Excel|Excel]]===
=DOLLAR(("4/"&A1)/7+MOD(19*MOD(A1,19)-7,30)*14%,)*7-6
=DOLLAR(("4/"&A1)/7+MOD(19*MOD(A1,19)-7,30)*14%,)*7-6
: Предполагается, что ячейка A1 содержит год.<ref>{{cite web|last=Walkenbach|first=John|title=Calculating Easter|url=http://spreadsheetpage.com/index.php/tip/calculating_easter/|archiveurl=http://www.webcitation.org/6FcDT117e|archivedate=2013-04-04}}</ref> Формула вычисляет дату католической Пасхи и дает верный результат для 1900—2203 годов.
: Предполагается, что ячейка A1 содержит год.<ref>{{cite web|last=Walkenbach|first=John|title=Calculating Easter|url=http://spreadsheetpage.com/index.php/tip/calculating_easter/|archiveurl=http://www.webcitation.org/6FcDT117e|archivedate=2013-04-04}}</ref> Формула вычисляет дату католической Пасхи и даёт верный результат для 1900…2203 годов.


== [[w:Python|Python]] ==
===[[w:Go|Go]]===
<syntaxhighlight lang="go">
// computus.go

package computus

type Year = uint16
type Month = uint8
type Day = uint8

// easter вычисляет по данному фактору месяц и день Пасхи (приватная функция).
func easter(factor Year) (Month, Day) {
return Month(factor / 31), Day(factor % 31 + 1)
}

// Alexandrian вычисляет для данного года месяц и день православной Пасхи (юлианская дата).
func Alexandrian(year Year) (Month, Day) {
d := (year % 19 * 19 + 15) % 30
return easter(d + (year % 4 * 2 + year % 7 * 4 + 34 - d) % 7 + 114)
}

// Gregorian вычисляет для данного года месяц и день католической Пасхи (григорианская дата).
func Gregorian(year Year) (Month, Day) {
a := year % 19
b := year / 100
c := year % 100
h := (19 * a + b - b / 4 - (b - (b + 8) / 25 + 1) / 3 + 15) % 30
l := (32 + (b % 4 + c / 4) * 2 - h - c % 4) % 7
return easter(h + l - (11 * (h + l + l) + a) / 451 * 7 + 114)
}
</syntaxhighlight>
Пример использования:
<syntaxhighlight lang="go">
// computus_test.go

package main

import (
"computus"
"fmt"
)

// printDate выводит дату в формате:
// К: ГГГГ-ММ-ДД
// где К — название календаря, ГГГГ — год, ММ — двузначный номер месяца, ДД — двузначное число.
func printDate(calendar string, year Year, month Month, day Day) {
fmt.Printf("%s: %d-%02d-%02d\n", calendar, year, month, day)
}

func main() {
var year computus.Year
print("Year? ")
fmt.Scanln(&year)

var month computus.Month
var day computus.Day

month, day = computus.Alexandrian(year)
printDate("Alexandrian", year, month, day)

month, day = computus.Gregorian(year)
printDate("Gregorian", year, month, day)
}
</syntaxhighlight>

===[[w:Pascal|Pascal]], [[w:Delphi|Delphi]]===
<syntaxhighlight lang="pascal">
{ computus.pas }

UNIT Computus;

INTERFACE

TYPE
TYear = Word;
TMonth = 1..12;
TDay = 1..31;

{
GetAlexandrian вычисляет для данного года месяц и день православной Пасхи (юлианская дата).
}
procedure GetAlexandrian(year: TYear; var month: TMonth; var day: TDay);

{
GetGregorian вычисляет для данного года месяц и день католической Пасхи (григорианская дата).
}
procedure GetGregorian(year: TYear; var month: TMonth; var day: TDay);

IMPLEMENTATION

{
_Easter вычисляет по данному фактору месяц и день Пасхи (приватная функция).
}
procedure _GetEaster(factor: TYear; var month: TMonth; var day: TDay);
begin
month := factor div 31;
day := factor mod 31 + 1
end;

procedure GetAlexandrian(year: TYear; var month: TMonth; var day: TDay);
var d: TYear;
begin
d := (year mod 19 * 19 + 15) mod 30;
_GetEaster(d + (year mod 4 * 2 + year mod 7 * 4 + 34 - d) mod 7 + 114, month, day)
end;

procedure GetGregorian(year: TYear; var month: TMonth; var day: TDay);
var a, b, c, h, l: TYear;
begin
a := year mod 19;
b := year div 100;
c := year mod 100;
h := (19 * a + b - b div 4 - (b - (b + 8) div 25 + 1) div 3 + 15) mod 30;
l := (32 + (b mod 4 + c div 4) * 2 - h - c mod 4) mod 7;
_GetEaster(h + l - (11 * (h + l + l) + a) div 451 * 7 + 114, month, day)
end;

END.
</syntaxhighlight>
Пример использования:
<syntaxhighlight lang="pascal">
{ computus_test.pas }

PROGRAM ComputusTest;

USES Computus;

VAR year: Computus.TYear;
month: Computus.TMonth;
day: Computus.TDay;

{
PrintDate выводит дату в формате:
К: ГГГГ-ММ-ДД
где К — название календаря, ГГГГ — год, ММ — двузначный номер месяца, ДД — двузначное число.
}
procedure PrintDate(calendar: String; year: TYear; month: TMonth; day: TDay);
begin
Write(calendar, ': ', year, '-');
if month < 10 then
Write('0');
Write(month, '-');
if day < 10 then
Write('0');
WriteLn(day)
end;

BEGIN
Write('Year? ');
ReadLn(year);

Computus.GetAlexandrian(year, month, day);
PrintDate('Alexandrian', year, month, day);

Computus.GetGregorian(year, month, day);
PrintDate('Gregorian', year, month, day)
END.
</syntaxhighlight>

===[[w:Perl|Perl]]===
: Rich Bowen’s модуль ''Date::Easter'' доступен на сайте CPAN .<ref>{{cite web|title=Date::Easter|url=http://search.cpan.org/~rbow/Date-Easter-1.14/lib/Date/Easter.pm|publisher=CPAN|archiveurl=http://www.webcitation.org/6FcDSMkSb|archivedate=2013-04-04}}</ref>

===[[w:Python|Python]]===
<syntaxhighlight lang="python">
<syntaxhighlight lang="python">
# computus.py
def IanTaylorEasterJscr(year):

def _easter(factor):
"""
_easter вычисляет по данному фактору месяц и день Пасхи (приватная функция).
"""
return factor // 31, factor % 31 + 1

def alexandrian(year):
"""
alexandrian вычисляет для данного года месяц и день православной Пасхи (юлианская дата).
"""
d = (year % 19 * 19 + 15) % 30
return _easter(d + (year % 4 * 2 + year % 7 * 4 + 34 - d) % 7 + 114)

def gregorian(year):
"""
gregorian вычисляет для данного года месяц и день католической Пасхи (григорианская дата).
"""
a = year % 19
a = year % 19
b = year >> 2
b = year // 100
c = b // 25 + 1
c = year % 100
d = (c * 3) >> 2
h = (19 * a + b - b // 4 - (b - (b + 8) // 25 + 1) // 3 + 15) % 30
e = ((a * 19) - ((c * 8 + 5) // 25) + d + 15) % 30
l = (32 + (b % 4 + c // 4) * 2 - h - c % 4) % 7
e += (29578 - a - e * 32) >> 10
return _easter(h + l - (11 * (h + l + l) + a) // 451 * 7 + 114)
</syntaxhighlight>
e -= ((year % 7) + b - d + e + 2) % 7
Пример использования:
d = e >> 5
<syntaxhighlight lang="python">
day = e - d * 31
# computus_test.py
month = d + 3
return year, month, day
</syntaxhighlight><br />


import computus
== [[w:C++|C++]] ==
<syntaxhighlight lang="cpp">
class Date
{
public:
int day;
int month;
int year;
};


// возвращает дату григорианского календаря
// по книге Jean Meeus Astronomical Algorithms
Date CatholicEaster( int year )
{
Date easterDate;


def print_date(calendar, year, month, day):
int a = year % 19;
"""
int b = year / 100;
print_date выводит дату в формате:
int c = year % 100;
К: ГГГГ-ММ-ДД
int d = b / 4;
где К — название календаря, ГГГГ — год, ММ — двузначный номер месяца, ДД — двузначное число.
int e = b % 4;
"""
int f = (b + 8) / 25;
print("%s: %d-%02d-%02d" % (calendar, year, month, day))
int g = (b - f + 1) / 3;
int h = (19 * a + b - d - g + 15) % 30;
int i = c / 4;
int k = c % 4;
int l = (32 + 2 * e + 2 * i - h - k) % 7;
int m = (a + 11 * h + 22 * l) / 451;
int month = (h + l - 7 * m + 114) / 31;
int day = ((h + l - 7 * m + 114) % 31) + 1;


year = int(input("Year? "))
easterDate.day = day;
easterDate.month = month;
easterDate.year = year;


month, day = computus.alexandrian(year)
return easterDate;
print_date("Alexandrian", year, month, day)

month, day = computus.gregorian(year)
print_date("Gregorian", year, month, day)
</syntaxhighlight>

===[[w:Rust|Rust]]===
<syntaxhighlight lang="rust">
// computus.rs

type Year = u16;
type Month = u8;
type Day = u8;

// easter вычисляет по данному фактору месяц и день Пасхи (приватная функция).
fn _easter(factor: Year) -> (Month, Day) {
((factor / 31) as Month, (factor % 31 + 1) as Day)
}
}


// Alexandrian вычисляет для данного года месяц и день православной Пасхи (юлианская дата).
// возвращает дату юлианского календаря
pub fn alexandrian(year: Year) -> (Month, Day) {
// по книге Jean Meeus Astronomical Algorithms
let d = (year % 19 * 19 + 15) % 30;
Date OrthodoxEaster( int year )
_easter(d + (year % 4 * 2 + year % 7 * 4 + 34 - d) % 7 + 114)
{
}
Date easterDate;


// Gregorian вычисляет для данного года месяц и день католической Пасхи (григорианская дата).
int a = year % 4;
pub fn gregorian(year: Year) -> (Month, Day) {
int b = year % 7;
int c = year % 19;
let a = year % 19;
int d = (19 * c + 15) % 30;
let b = year / 100;
int e = (2 * a + 4 * b - d + 34) % 7;
let c = year % 100;
int month = (d + e + 114) / 31;
let h = (19 * a + b - b / 4 - (b - (b + 8) / 25 + 1) / 3 + 15) % 30;
int day = ((d + e + 114) % 31) + 1;
let l = (32 + (b % 4 + c / 4) * 2 - h - c % 4) % 7;
_easter(h + l - (11 * (h + l + l) + a) / 451 * 7 + 114)
}
</syntaxhighlight>
Пример использования:
<syntaxhighlight lang="rust">
// computus_test.rs

mod computus;

// read_var считывает данные из стандартного потока ввода.
fn read_var<Type: std::str::FromStr>(var: &mut Type) -> bool {
let mut input_text = String::new();
std::io::stdin()
.read_line(&mut input_text)
.expect("Unable to read from standard input.");
match input_text.trim().parse::<Type>() {
Ok(value) => {
*var = value;
true
}
Err(..) => false,
}
}

// print_date выводит дату в формате:
// К: ГГГГ-ММ-ДД
// где К — название календаря, ГГГГ — год, ММ — двузначный номер месяца, ДД — двузначное число.
fn print_date(calendar: &str, year: computus::Year, (month, day): (computus::Month, computus::Day)) {
println!("{}: {}-{:02}-{:02}", calendar, year, month, day);
}


fn main() {
easterDate.day = day;
let mut year: computus::Year;
easterDate.month = month;
easterDate.year = year;


return easterDate;
print!("Year? ");
if read_var(&mut year) {
print_date("Alexandrian", year, alexandrian(year));
print_date("Gregorian", year, gregorian(year));
}
}
}
</syntaxhighlight>
</syntaxhighlight>

Версия от 20:02, 16 октября 2020

Пасха (англ. Easter) — христианский праздник воскресения Иисуса Христа, отмечающийся в первое воскресенье после первого полнолуния, наступающего не ранее весеннего равноденствия; таким образом он не привязан к конкретной дате («преходящий праздник»). Под полнолунием и равноденствием понимаются не фактические астрономические явления, а их расчётные даты: полнолуние вычисляется по Метонову циклу, за равноденствие берётся 21 марта (календарное равноденствие для северного полушария).

Пасхалия (англ. = лат. Computus — исчисление) — методика расчёта даты празднования Пасхи в том или ином году. В настоящее время большинство православных церквей используют александрийскую пасхалию, опирающуюся на юлианский календарь («старый стиль»), тогда как католическая, а также некоторые православные и протестантские церкви придерживаются григорианской, основанной на общепринятом григорианском календаре. Из-за расхождения между этими календарями (13 дней на сегодня) разница между датами празднования «католической» и «православной» Пасхи в разные годы может составлять 0, 1, 4 или 5 недель.

Описание

Существуют различные алгоритмы пасхалии. Здесь использован алгоритм григорианской пасхалии неизвестного автора (журнал New York correspondent, 1876) и его адаптация бельгийским математиком-астрономом Жаном Меёсом (франц. Jean Meeus) для александрийской пасхалии (Jean Meeus - Astronomical Algorithms, 1991).

Дано: год

Найти: месяц, день

Вычисляется фактор. ЦЕЛ(x) означает целую часть выражения, ОСТ(x / y) — остаток от деления.

Александрийская пасхалия:

d = ОСТ((ОСТ(год / 19) × 19 + 15) / 30)
factor = d + ОСТ(((ОСТ(год / 4) × 2) + (ОСТ(год / 7) × 4) + 34 − d) / 7) + 114

Григорианская пасхалия:

a = ОСТ(год / 19)
b = ЦЕЛ(год / 100)
c = ОСТ(год / 100)
h = ОСТ((19 × a + b − ЦЕЛ(b / 4) − ЦЕЛ((b − ЦЕЛ((b + 8) / 25) + 1) / 3) + 15) / 30)
l = ОСТ((32 + (ОСТ(b / 4) + ЦЕЛ(c / 4)) × 2 − h − ОСТ(c / 4)) / 7)
factor = h + l − ЦЕЛ((11 × (h + 2 × l) + a) / 451) × 7 + 114

Месяц и день Пасхи вычисляются из фактора:

месяц = ЦЕЛ(factor / 31)
день = ОСТ(factor / 31) + 1

Для григорианской пасхи найденные значения определяют григорианскую дату, а для александрийской — юлианскую.

Реализации

PowerBASIC, QBASIC, QuickBasic версий 4.X, Visual Basic версий ≤ 6.0, Visual Basic для приложений

' computus.bas

' ComputusGetEaster вычисляет по данному фактору месяц и день Пасхи (приватная функция).
Sub ComputusGetEaster(factor As Integer, month As Integer, day As Integer)
    month = factor \ 31
    day = factor Mod 31 + 1
End Sub

' ComputusGetAlexandrian вычисляет для данного года месяц и день православной Пасхи (юлианская дата).
Sub ComputusGetAlexandrian(year As Integer, month As Integer, day As Integer)
    Dim d As Integer
    d = (year Mod 19 * 19 + 15) Mod 30
    ComputusGetEaster d + (year Mod 4 * 2 + year Mod 7 * 4 + 34 - d) Mod 7 + 114, month, day
End Sub

' ComputusGetGregorian вычисляет для данного года месяц и день католической Пасхи (григорианская дата).
Sub ComputusGetGregorian(year As Integer, month As Integer, day As Integer)
    Dim a As Integer, b As Integer, c As Integer, h As Integer, l As Integer
    a = year Mod 19
    b = year \ 100
    c = year Mod 100
    h = (19 * a + b - b \ 4 - (b - (b + 8) \ 25 + 1) \ 3 + 15) Mod 30
    l = (32 + (b Mod 4 + c \ 4) * 2 - h - c Mod 4) Mod 7
    ComputusGetEaster h + l - (11 * (h + l + l) + a) \ 451 * 7 + 114, month, day
End Sub

Пример использования:

' comptest.bas

' PrintDate выводит дату в формате:
' К: ГГГГ-ММ-ДД
' где К — название календаря, ГГГГ — год, ММ — двузначный номер месяца, ДД — двузначное число.
Sub PrintDate(calendar As String, year As Integer, month As Integer, day As Integer)
    Print calendar; ": ";
    Print year; "-";
    If month < 10 Then Print "0";
    Print Str(month); "-";
    If day < 10 Then Print "0";
    Print Str(day)
End Sub

' Для Visual Basic добавить здесь Sub Main

Dim year As Integer

Input "Year", year

Dim month As Integer, day As Integer

ComputusGetAlexandrian year, month, day
PrintDate "Alexandrian", year, month, day

ComputusGetGregorian year, month, day
PrintDate "Gregorian", year, month, day

' Для Visual Basic добавить здесь End Sub

C

/* computus.h */

#ifndef _COMPUTUS_H_
#define _COMPUTUS_H_


typedef unsigned short Year;
typedef unsigned char Month;
typedef unsigned char Day;

/*
computus_get_alexandrian вычисляет для данного года месяц и день православной Пасхи (юлианская дата).
*/
void computus_get_alexandrian(Year year, Month *month, Day *day);

/*
computus_get_gregorian вычисляет для данного года месяц и день католической Пасхи (григорианская дата).
*/
void computus_get_gregorian(Year year, Month *month, Day *day);


#endif


/* computus.c */

#include "computus.h"


/*
_computus_get_easter вычисляет по данному фактору месяц и день Пасхи (приватная функция).
*/
void _computus_get_easter(Year factor, Month *month, Day *day) {
    *month = Month(factor / 31);
    *day = Day(factor % 31 + 1);
}

void computus_get_alexandrian(Year year, Month *month, Day *day) {
    Year d = (year % 19 * 19 + 15) % 30;
    _computus_get_easter(d + (year % 4 * 2 + year % 7 * 4 + 34 - d) % 7 + 114, month, day);
}

void computus_get_gregorian(Year year, Month *month, Day *day) {
    Year
        a = year % 19,
        b = year / 100,
        c = year % 100,
        h = (19 * a + b - b / 4 - (b - (b + 8) / 25 + 1) / 3 + 15) % 30,
        l = (32 + (b % 4 + c / 4) * 2 - h - c % 4) % 7;
    _computus_get_easter(h + l - (11 * (h + l + l) + a) / 451 * 7 + 114, month, day);
}

Пример использования:

/* computus_test.c */

#include <stdio.h>

#include "computus.h"


/*
print_date выводит дату в формате:
К: ГГГГ-ММ-ДД
где К — название календаря, ГГГГ — год, ММ — двузначный номер месяца, ДД — двузначное число.
*/
void print_date(const char *calendar, Year year, Month month, Day day) {
    printf("%s: %hu-%.2hu-%.2hu\n", calendar, year, month, day);
}

int main() {
    Year year;
    printf("Year? ");
    scanf("%hu", &year);

    Month month;
    Day day;

    computus_get_alexandrian(year, &month, &day);
    print_date("Alexandrian", year, month, day);

    computus_get_gregorian(year, &month, &day);
    print_date("Gregorian", year, month, day);
}

C++

// computus.hpp

#pragma once


namespace computus {

    typedef unsigned short Year;
    typedef unsigned char Month;
    typedef unsigned char Day;

    // getAlexandrian вычисляет для данного года месяц и день православной Пасхи (юлианская дата).
    void getAlexandrian(Year year, Month &month, Day &day);

    // getGregorian вычисляет для данного года месяц и день католической Пасхи (григорианская дата).
    void getGregorian(Year year, Month &month, Day &day);

}


// computus.cpp

#include "computus.hpp"


namespace computus {

    // _getEaster вычисляет по данному фактору месяц и день Пасхи (приватная функция).
    void _getEaster(Year factor, Month &month, Day &day) {
        month = Month(factor / 31);
        day = Day(factor % 31 + 1);
    }

    void getAlexandrian(Year year, Month &month, Day &day) {
        Year d = (year % 19 * 19 + 15) % 30;
        _getEaster(d + (year % 4 * 2 + year % 7 * 4 + 34 - d) % 7 + 114, month, day);
    }
    
    void getGregorian(Year year, Month &month, Day &day) {
        Year
            a = year % 19,
            b = year / 100,
            c = year % 100,
            h = (19 * a + b - b / 4 - (b - (b + 8) / 25 + 1) / 3 + 15) % 30,
            l = (32 + (b % 4 + c / 4) * 2 - h - c % 4) % 7;
        _getEaster(h + l - (11 * (h + l + l) + a) / 451 * 7 + 114, month, day);
    }

}

Пример использования:

// computus_test.cpp

#include <iostream>
#include <iomanip>

#include "computus.hpp"


// printDate выводит дату в формате:
// К: ГГГГ-ММ-ДД
// где К — название календаря, ГГГГ — год, ММ — двузначный номер месяца, ДД — двузначное число.
void printDate(const char *calendar, computus::Year year, computus::Month month, computus::Day day) {
    std::cout
        << calendar << ':' << ' ' << year
        << '-' << std::setw(2) << std::setfill('0') << int(month)
        << '-' << std::setw(2) << std::setfill('0') << int(day)
        << '\n';
}

int main() {
    computus::Year year;
    std::cout << "Year? ";
    std::cin >> year;

    computus::Month month;
    computus::Day day;

    computus::getAlexandrian(year, month, day);
    printDate("Alexandrian", year, month, day);

    computus::getGregorian(year, month, day);
    printDate("Gregorian", year, month, day);
}

Excel

=DOLLAR(("4/"&A1)/7+MOD(19*MOD(A1,19)-7,30)*14%,)*7-6
Предполагается, что ячейка A1 содержит год.[1] Формула вычисляет дату католической Пасхи и даёт верный результат для 1900…2203 годов.

Go

// computus.go

package computus

type Year = uint16
type Month = uint8
type Day = uint8

// easter вычисляет по данному фактору месяц и день Пасхи (приватная функция).
func easter(factor Year) (Month, Day) {
	return Month(factor / 31), Day(factor % 31 + 1)
}

// Alexandrian вычисляет для данного года месяц и день православной Пасхи (юлианская дата).
func Alexandrian(year Year) (Month, Day) {
	d := (year % 19 * 19 + 15) % 30
	return easter(d + (year % 4 * 2 + year % 7 * 4 + 34 - d) % 7 + 114)
}

// Gregorian вычисляет для данного года месяц и день католической Пасхи (григорианская дата).
func Gregorian(year Year) (Month, Day) {
	a := year % 19
	b := year / 100
	c := year % 100
	h := (19 * a + b - b / 4 - (b - (b + 8) / 25 + 1) / 3 + 15) % 30
	l := (32 + (b % 4 + c / 4) * 2 - h - c % 4) % 7
	return easter(h + l - (11 * (h + l + l) + a) / 451 * 7 + 114)
}

Пример использования:

// computus_test.go

package main

import (
	"computus"
	"fmt"
)

// printDate выводит дату в формате:
// К: ГГГГ-ММ-ДД
// где К — название календаря, ГГГГ — год, ММ — двузначный номер месяца, ДД — двузначное число.
func printDate(calendar string, year Year, month Month, day Day) {
	fmt.Printf("%s: %d-%02d-%02d\n", calendar, year, month, day)
}

func main() {
	var year computus.Year
	
	print("Year? ")
	fmt.Scanln(&year)

	var month computus.Month
	var day computus.Day

	month, day = computus.Alexandrian(year)
	printDate("Alexandrian", year, month, day)

	month, day = computus.Gregorian(year)
	printDate("Gregorian", year, month, day)
}

Pascal, Delphi

{ computus.pas }

UNIT Computus;

INTERFACE

    TYPE
        TYear = Word;
        TMonth = 1..12;
        TDay = 1..31;

    {
    GetAlexandrian вычисляет для данного года месяц и день православной Пасхи (юлианская дата).
    }
    procedure GetAlexandrian(year: TYear; var month: TMonth; var day: TDay);

    {
    GetGregorian вычисляет для данного года месяц и день католической Пасхи (григорианская дата).
    }
    procedure GetGregorian(year: TYear; var month: TMonth; var day: TDay);

IMPLEMENTATION

    {
    _Easter вычисляет по данному фактору месяц и день Пасхи (приватная функция).
    }
    procedure _GetEaster(factor: TYear; var month: TMonth; var day: TDay);
    begin
        month := factor div 31;
        day := factor mod 31 + 1
    end;

    procedure GetAlexandrian(year: TYear; var month: TMonth; var day: TDay);
    var d: TYear;
    begin
        d := (year mod 19 * 19 + 15) mod 30;
        _GetEaster(d + (year mod 4 * 2 + year mod 7 * 4 + 34 - d) mod 7 + 114, month, day)
    end;

    procedure GetGregorian(year: TYear; var month: TMonth; var day: TDay);
    var a, b, c, h, l: TYear;
    begin
        a := year mod 19;
        b := year div 100;
        c := year mod 100;
        h := (19 * a + b - b div 4 - (b - (b + 8) div 25 + 1) div 3 + 15) mod 30;
        l := (32 + (b mod 4 + c div 4) * 2 - h - c mod 4) mod 7;
        _GetEaster(h + l - (11 * (h + l + l) + a) div 451 * 7 + 114, month, day)
    end;

END.

Пример использования:

{ computus_test.pas }

PROGRAM ComputusTest;

USES Computus;

VAR year: Computus.TYear;
    month: Computus.TMonth;
    day: Computus.TDay;

{
PrintDate выводит дату в формате:
К: ГГГГ-ММ-ДД
где К — название календаря, ГГГГ — год, ММ — двузначный номер месяца, ДД — двузначное число.
}
procedure PrintDate(calendar: String; year: TYear; month: TMonth; day: TDay);
begin
    Write(calendar, ': ', year, '-');
    if month < 10 then
        Write('0');
    Write(month, '-');
    if day < 10 then
        Write('0');
    WriteLn(day)
end;

BEGIN
    Write('Year? ');
    ReadLn(year);

    Computus.GetAlexandrian(year, month, day);
    PrintDate('Alexandrian', year, month, day);

    Computus.GetGregorian(year, month, day);
    PrintDate('Gregorian', year, month, day)
END.

Perl

Rich Bowen’s модуль Date::Easter доступен на сайте CPAN .[2]

Python

# computus.py

def _easter(factor):
    """
    _easter вычисляет по данному фактору месяц и день Пасхи (приватная функция).
    """
    return factor // 31, factor % 31 + 1

def alexandrian(year):
    """
    alexandrian вычисляет для данного года месяц и день православной Пасхи (юлианская дата).
    """
    d = (year % 19 * 19 + 15) % 30
    return _easter(d + (year % 4 * 2 + year % 7 * 4 + 34 - d) % 7 + 114)

def gregorian(year):
    """
    gregorian вычисляет для данного года месяц и день католической Пасхи (григорианская дата).
    """
    a = year % 19
    b = year // 100
    c = year % 100
    h = (19 * a + b - b // 4 - (b - (b + 8) // 25 + 1) // 3 + 15) % 30
    l = (32 + (b % 4 + c // 4) * 2 - h - c % 4) % 7
    return _easter(h + l - (11 * (h + l + l) + a) // 451 * 7 + 114)

Пример использования:

# computus_test.py

import computus


def print_date(calendar, year, month, day):
    """
    print_date выводит дату в формате:
    К: ГГГГ-ММ-ДД
    где К — название календаря, ГГГГ — год, ММ — двузначный номер месяца, ДД — двузначное число.
    """
    print("%s: %d-%02d-%02d" % (calendar, year, month, day))

year = int(input("Year? "))

month, day = computus.alexandrian(year)
print_date("Alexandrian", year, month, day)

month, day = computus.gregorian(year)
print_date("Gregorian", year, month, day)

Rust

// computus.rs

type Year = u16;
type Month = u8;
type Day = u8;

// easter вычисляет по данному фактору месяц и день Пасхи (приватная функция).
fn _easter(factor: Year) -> (Month, Day) {
    ((factor / 31) as Month, (factor % 31 + 1) as Day)
}

// Alexandrian вычисляет для данного года месяц и день православной Пасхи (юлианская дата).
pub fn alexandrian(year: Year) -> (Month, Day) {
    let d = (year % 19 * 19 + 15) % 30;
    _easter(d + (year % 4 * 2 + year % 7 * 4 + 34 - d) % 7 + 114)
}

// Gregorian вычисляет для данного года месяц и день католической Пасхи (григорианская дата).
pub fn gregorian(year: Year) -> (Month, Day) {
    let a = year % 19;
    let b = year / 100;
    let c = year % 100;
    let h = (19 * a + b - b / 4 - (b - (b + 8) / 25 + 1) / 3 + 15) % 30;
    let l = (32 + (b % 4 + c / 4) * 2 - h - c % 4) % 7;
    _easter(h + l - (11 * (h + l + l) + a) / 451 * 7 + 114)
}

Пример использования:

// computus_test.rs

mod computus;

// read_var считывает данные из стандартного потока ввода.
fn read_var<Type: std::str::FromStr>(var: &mut Type) -> bool {
    let mut input_text = String::new();
    std::io::stdin()
        .read_line(&mut input_text)
        .expect("Unable to read from standard input.");
    match input_text.trim().parse::<Type>() {
        Ok(value) => {
            *var = value;
            true
        }
        Err(..) => false,
    }
}

// print_date выводит дату в формате:
// К: ГГГГ-ММ-ДД
// где К — название календаря, ГГГГ — год, ММ — двузначный номер месяца, ДД — двузначное число.
fn print_date(calendar: &str, year: computus::Year, (month, day): (computus::Month, computus::Day)) {
    println!("{}: {}-{:02}-{:02}", calendar, year, month, day);
}

fn main() {
    let mut year: computus::Year;

    print!("Year? ");
    if read_var(&mut year) {
        print_date("Alexandrian", year, alexandrian(year));
        print_date("Gregorian", year, gregorian(year));
    }
}

Примечания