Вопрос № 37275: Здравствуйте, уважаемые эксперты!
В одном учебнике по программированию на Паскале (Рапаков Г.Г., Ржеуцкая С.Ю. Программирование на языке Pascal) встретилась интересная задача - составить программу, определяющую день недели известной даты по совре...
Вопрос № 37.275
Здравствуйте, уважаемые эксперты!
В одном учебнике по программированию на Паскале (Рапаков Г.Г., Ржеуцкая С.Ю. Программирование на языке Pascal) встретилась интересная задача - составить программу, определяющую день недели известной даты по современному европейскому календарю и приводится такой листинг:
var d,m,y:integer; n:longint;
begin
writeln('введите день, месяц, год даты (например: 3 12 1964)');
readln(d,m,y);
if (m>=2) then m:=m+1
else
begin
m:=m+13; y:=y-1;
end;
n:=trunc(365.25*y)+trunc(30.6*m)+d-621050;
n:=n-trunc(n/7)*7+1;
case n of
1: write('понедельник');
2: write('вторник');
3: write('среда');
4: write('четверг');
5: write('пятница');
6: write('суббота');
7: write('воскресенье');
end;
writeln;
end.
Я набирала в Pascal, программа работает. Но алгоритм решения для меня остается абсолютно непонятным. Особенно неясно, откуда берется число 621050. Если нетрудно, пожалуйста, не могли бы вы объяснить эту программу? Я понимаю, наверное, это классическая, элементарная и всем известная задача... но я не волшебник, я только учусь :)
Заранее огромное спасибо,
Helga
Отправлен: 11.03.2006, 19:37
Вопрос задала: Sphinx2005 (статус: Посетитель)
Всего ответов: 1 Мини-форум вопроса >>> (сообщений: 1)
Отвечает: Полховский Александр Владимирович
Здравствуйте, Sphinx2005!
Я там на мини-форуме чуток напутал. Оказалось всё ещё сложнее. Ну, поехали.
Во-первых, 01.01.0001 г. - Понедельник, а не Воскресенье, как я раньше сказал.
Во-вторых, 29-й день Февраля появляется в каждом четвёртом году (0004, 0008...) за исключением каждого сотого года (0100, 0200...), при этом в каждом четырёхсотом году он все же появляется (0400, 0800, 1200, 1600, 2000...).
Таким образом, при подсчёте количества минувших с 01.01.0001 дней необходимо учитывать исчезновение в каждом сотом году 29-го дня Февраля, кроме каждых четырёхсотых.
Вот распределение количества дней в году (Феврале) в зависимости от года: (в приложении, а то читать не удобно).
Надеюсь, понятно.
Ну а дальше, как и ранее, банальные пересчёт с учётом всех этих условий: (3 edit'a для числа, месяца и года, ещё 1 (пятый) для вывода результата; ну это Вы сами разберётесь, думаю)
procedure TForm1.Button3Click(Sender: TObject);
var
n, ny, d, m, y:longint;
begin
d:=strtoint(edit1.Text);//в формате DD (01, 02, 03...)
m:=strtoint(edit2.Text);//в формате MM (01, 02, 03...)
y:=strtoint(edit3.Text);//в формате YYYY (0001, 0002, 2003...)
ny:=y;
n:=trunc(365.25*ny)-365+ny div 400-ny div 100;//-365 за счёт того, что первый год был не 0000; каждые 100 лет убирают 29 Февраля, кроме каждого четырёхсотого года
if (m<=2)and(y mod 4=0)//если год високосный, но ещё не прошёл Февраль, то 29-й день не добавился (если должен был)
then n:=n-1-ord(ny mod 400=0)+ord(ny mod 100=0); //и ещё не отнялся (если должен был) день за 400 лет и не прибавился за 100 лет
//далее заменяем рассчёт поочерёдной проверко, так понятнее, откуда количество дней выплывает
//полностью прошёл месяц - добавили его количество дней
if m>1
then n:=n+31;//если позже Января
if m>2
then n:=n+28;//если позже Февраля (29-й день уже прибавился за счёт 365,25 дней в году)
if m>3
then n:=n+31;//если позже Марта
if m>4
then n:=n+30;//если позже Апреля
if m>5
then n:=n+31;//если позже Мая
if m>6
then n:=n+30;//если позже Июня
if m>7
then n:=n+31;//если позже Июля
if m>8
then n:=n+31;//если позже Августа
if m>9
then n:=n+30;//если позже Сентября
if m>10
then n:=n+31;//если позже Октября
if m>11
then n:=n+30;//если позже Ноября
n:=n+d-1;//прибавляем количество дней, прошедших за текущий месяц, отнимаем начальное первое число отсчёта (01.01.0001)
n:=(n)mod(7)+1; //убираем целое число прошедших недель, и анализируем остаток; +1 так как mod даст от 0 до 6, а нам надо от 1 до 7
case n of
1: Edit5.Text:='понедельник';
2: Edit5.Text:='вторник';
3: Edit5.Text:='среда';
4: Edit5.Text:='четверг';
5: Edit5.Text:='пятница';
6: Edit5.Text:='суббота';
7: Edit5.Text:='воскресенье';
end;
end;