Составить функцию JD, вычисляющую юлианскую
Задание 9.01. Вычисления юлианских дат
Составить функцию JD, вычисляющую юлианскую дату по году (Y), номеру месяца (м), номеру дня и значению времени, заданным в виде вещественного числа от (целая часть от — порядковый номер дня в месяце, дробная часть от — часть суток, прошедшая после полуночи). Проверки на правильность задания исходной информации исключены, чтобы не загромождать текст программы.
Совет 1 (общий)
По результатам довольно обширного численного эксперимента мы выяснили, что наиболее точный алгоритм представлен формулами Меёса. Поэтому тексты приводимых ниже программ используют алгоритм JD2. Если ваши задачи относятся к более узким временным интервалам, то текст функции JD можно заменить, используя один из выше описанных алгоритмов.
Программа 9_01.bas
DECLARE FUNCTION JD! (Y%, M%, DT!)
REM Перевод даты григорианского календаря
REM в юлианскую дату (алгоритм Меёса)
CLS
INPUT "Задайте год григорианского календаря : ",Y%
INPUT "Задайте месяц григорианского календаря : ",М%
INPUT "Задайте день и время : ",DT
PRINT USING "##### ### ###.#";Y%;M%;DT;
jdl=JD(Y%,M%,DT)
PRINT USING " JD =#########.#####";jdl
END
FUNCTION JD(Y%,M%,DT)
' Y - григорианский год [-4713,9999]
' М - григорианский месяц [1,12]
' целая часть DT - день [1,31]
' дробная часть DT - время, прошедшее
' от начала текущего дня [.0,.99999]
' Возвращаемое значение - юлианская дата
' Целая часть JD - число дней, прошедших
' от 1 января 4713 года до новой эры
' Дробная часть JD - время, прошедшее
' после 12 часов полудня дня JD
b%=0: yy%=Y%: mm%=M%
IF M%<3 THEN уу%=уу%-1: mm%=mm%+12
а%=уу% \ 100
IF Y%+M% / 1001+DT/10000 > 1582.10151 THEN
b%=b%+2-a%+(a% \ 4} END IF
c&=INT(365.25*yy%)
IF yy%<0 THEN c&=INT(365.25*yy%-.75)
JD=c&+INT(30.6001*(mm%+l))+DT+1720994.5#+b%
END FUNCTION
Программа 9_01.с
#include <stdio.h>
#include <conio.h>
#include <math.h>
double JD (int Y,int M,double DT);
main() {
int Y,M,day;
double DT,jd;
clrscr();
printf("\ n Задайте год григорианского календаря : ");
scanf("%d",&Y);
printf("\n Задайте месяц григорианского календаря : ");
scanf("%d",SM);
printf("\n Задайте день и время : ");
scanf("%lf",&DT);
jd=JD(Y,M,DT);
printf("\n JD =%15.5f",jd);
getch();
}
/*----------------------------------------* /
/*----------------------------------------* /
double JD(int Y,int M,double DT)
/*******************************************/
/* Перевод даты григорианского календаря */
/* в юлианскую дату (алгоритм Меёса) */
/* Y - григорианский год [-4713,9999] */
/* М - григорианский месяц [1,12] */
/* целая часть DT - день [1,31] */
/* дробная часть DT - время, прошедшее */
/* от начала текущего дня [.0,.99999] */
/* Возвращаемое значение - юлианская дата */
/* Целая часть JD - число дней, прошедших */
/* от 1 января 4713 года до новой эры */
/* Дробная часть JD - время, прошедшее */
/* после 12 часов полудня дня JD */
{
int a,b=0,m,y;
long с;
y=Y;
m=M;
if (M<3) { y--; m += 12; }
a=y/100;
if(Y+M/100.+DT/10000 > 1582.1015)
b += 2-a+(int)(a/4.);
c=365.25*y;
if(y<0)c=365.25*y-0.75;
return c+(long)(30.6001*(m+1))+DT+1720994.5+b; }
Программа 9_01.pas
program gd_t6_jd;
uses Crt;
var
Y,M,day:integer; DT,jdl:double;
function JD(Y,M:integer;DT:double):double;
{ Перевод даты григорианского календаря }
{ в юлианскую дату (алгоритм Меёса) }
{ Y - григорианский год [-4713,9999] }
{ М - григорианский месяц [1,12] }
{ целая часть DT - день [1,31] }
{ дробная часть DT - время, прошедшее }
{ от начала текущего дня [.0,.99999] }
{ Возвращаемое значение - юлианская дата }
{ Целая часть JD - число дней, прошедших }
( от 1 января 4713 года до новой эры }
{ Дробная часть JD - время, прошедшее }
{ после 12 часов полудня дня JD }
var
a,b,mm,yy:integer;
с:longint; begin
b:=0;
yy:=Y;
mm:=M;
if M<3 then begin yy:=yy-l;
mm:=mm+12;
end;
a:=yy div 100;
if (Y+M/100.+DT/10000)>1582.1015 then b:=b+2-a+(a div 4);
c:=trunc(365.25*yy);
if yy<0 then c:=trunc(365.25*yy-0.75) ;
JD:=c+trunc(30.6001*(mm+1))+DT+1720994.5+b;
end;
begin
clrscr;
write('Задайте год григорианского календаря : ');
readln(Y);
write('Задайте месяц григорианского календаря : ');
readln(M);
write('Задайте день и время : ');
readln(DT);
write(Y:4,M:3, ' ',DT:3:1);
jdl:=JD(Y,M,DT);
writelnC JD =', jdl:15:5) ;
readln; end.
Задание 9.02. Вычисление дат григорианского календаря
Составить подпрограмму GD, вычисляющую дату григорианского календаря по юлианской дате, представленной вещественным числом JD.
Совет 1 (общий)
Учитывая высокое качество алгоритмов Меёса, воспользуемся его же алгоритмом для обратного преобразования дат. Мы тщательно проверили его на большом количестве прямых и обратных преобразований григорианских и юлианских дат. В приведенных ниже формулах сохранены обозначения Меёса.
Вычислим JD+0.5 и обозначим через z целую часть, а через F — дробную. Если z > 2299161, то вычислим:
a=int((Z-1867216.25)/36524.25) A=Z+l+a-int(a/4) при z < 2299161 положим
A=Z
В=А+1524
C=int((B-122.1)/365.25
D=int(365.25*C)
E=int((B-D)/30.6001)
DT=B-D-int(30.6001*E) Номер месяца
M=Е-1, если E<13.5
M=Е-13,если Е>13.5 Номер года
Y=C-4716,если м>2.5
Y=C-4715,если М<2.5
Программа 9_02.bas
DECLARE SUB GD(jd!,y%,m%,DT!)
REM Преобразование юлианской даты JD в дату григорианского
КЕМ календаря - Y (год), М (месяц),
REM DT (день и часть времени, прошедшую от начала суток
CLS
INPUT "Задайте юлианскую дату : ",jd
GD jd,y%,m%,DT
PRINT USING "год = ##### месяц = ## день и время = ####";y%;m%;DT
END
SUB GD(jd,y%,m%,DT)
' Восстановление даты григорианского календаря
' по юлианской дате jd. Результаты заносятся в
' у% - год
' m% - месяц
' dt - день (целая часть) и время дня (дробная часть)
DIM A AS LONG, В AS LONG, С AS LONG, D AS LONG, Z AS LONG
DIM aa AS LONG, E AS INTEGER, F AS DOUBLE
Z=INT(jd+.5)
F=jd+.5-Z
A=Z
IF Z>=2299161 THEN
aa=INT((Z-1867216.25#)/36524.25) A=A+l+aa-(aa\4)
END IF B=A+1524
C=INT((B-122.1)/365.25) D=INT(365.25*C) E=INT((B-D)/30.6001)
DT=B-D-INT(30.6001*E)+F
IF E<13.5 THEN m%=E-l
ELSE m%=E-13
IF m%>2.5 THEN y%=C-4716
ELSE y%=C-4715
END SUB
Программа 9_02.с
#include <stdio.h>
#include <conio.h>
void GD(double jd,int *y,int *m,double *dt);
main () (
int Y,M;
double DT,jd;
clrscr () ;
printf("\n Задайте юлианскую дату : ");
scanf("%lf",&jd);
GD(jd, &Y, &M, &DT) ;
printf("\n годl=%d месяц=%d день и время=%-15.51f",Y,M,DT);
getch();
}
/*--------------------------------------*/
void GD(double jd,int *y,int *m,double *dt)
/* Восстановление даты григорианского */
/* календаря по юлианской дате jd */
/* у - год, m - месяц */
/* dt - день (целая часть) */
/* и время дня (дробная часть) */
/**************************************/
{
long a,A,B,C,D,E, Z;
double F;
Z=jd+0.5;
F=jd+0.5-Z; A=Z;
if(Z>=2299161)
{
a=(Z-1867216.25)/36524.25;
A += l+a-a/4; }
B=A+1524;
C=(B-122.1)/365.25;
D=365.25*C; E=(B-D)/30.6001;
*dt=B-D-(int)(30.6001*E)+F;
if(E<13.5) *m=E-l;
else *m=E-13;
if(*m>2.5) *y=C-4716;
else *y=C-4715; }
Программа 9_02.pas
program jd_to_gd;
{ Преобразование юлианской даты JD в дату григорианского календаря - Y (год), М (месяц), DT (день и часть времени, прошедшую от начала суток }
uses crt; var
Y,M:integer;
DT,jd:double;
procedure GD(jd:double;
var y,m:integer; var dtrdouble);
{ Восстановление даты григорианского }
{ календаря по юлианской дате jd }
{ у - год, m - месяц }
{ dt - день (целая часть) }
( и время дня (дробная часть) }
var
aa,A,B,C,D,E,Z:longint;
F:double; begin
Z:=trunc(jd+0.5);
F:=jd+0.5-Z;
A:=Z;
if Z>=2299161 then begin
aa:=trunc((Z-1867216.25)/36524.25);
A:=A+l+aa-(aa div 4);
end;
B:=A+1524;
C:=trunc( (B-122.D/365.25) ;
D:=trunc(365.25*C);
E:=trunc((B-D)/30.6001);
dt:=B-D-trunc(30.6001*E)+F;
if E<13.5 then m:=E-l
else m:=E-13;
if m>2.5 then y:=C-4716
else y:=C-4715;
end;
begin
clrscr;
write('Задайте юлианскую дату : ');
readln(jd);
GD(jd,Y,M,DT);
writeln('год = ',Y:4,' месяц = ',M:2,' день и время = ',DT:4:1);
readln; end.
Задание 9.03. Интервал времени между двумя датами
Составить функцию dif_time, вычисляющую интервал между двумя датами григорианского календаря.
Совет 1 (общий)
Преобразуйте даты григорианского календаря и найдите разницу между соответствующими юлианскими датами. Чтобы не выяснять, какая из дат является предшествующей, можно найти модуль разности.
Программа 9_03.bas
DECLARE FUNCTION JD! (Y%, M%, DT!)
DECLARE FUNCTION DifTime! (Yl%, Ml%, DTI!, Y2%, M2%, DT2!)
REM Определение интервала времени между двумя датами
REM григорианского календаря : (Y1,M1,DT1) и (Y2,M2,DT2)
CLS
INPUT "Задайте год григорианского календаря : ",Y1%
INPUT "Задайте месяц григорианского календаря : ",М1%
INPUT "Задайте день и время : ",DT1
INPUT "Задайте год григорианского календаря : ",Y2%
INPUT "Задайте месяц григорианского календаря : ",М2%
INPUT "Задайте день и время : ",DT2
PRINT "Интервал =",DifTime(Y1%,M1%,DTI,Y2%,M2%,DT2)
END
FUNCTION DifTime (Y1%,M1%,DTI,Y2%,M2%,DT2)
' Определение интервала времени между
' двумя григорианскими датами
' Y1,Y2 - годы М1,М2 - месяцы
' целые части DTI, DT2 - дни
' дробные части DTI, DT2 - время дня
jdl=JD(Y1%,M1%,DT1)
jd2=JD(Y2%,M2%,DT2)
DifTime=ABS(jdl-jd2) END FUNCTION
FUNCTION JD(Y%,M%,DT)
DIM a AS INTEGER, b AS INTEGER, mm AS INTEGER, yy AS INTEGER
DIM с AS LONG
b=0
yy=Y%
mm=M%
IF M%<3 THEN yy=yy-l: mm=mm+12
а=уу\100
IF Y%+M%/100!+DT/10000>1582.1015# THEN
b=b+2-a+a\4 END IF
c=INT(365.25*yy)
IF yy<0 THEN
c=INT(365.25*yy-.75)
JD=c+INT(30.6001*(iran+1))+DT+1720994.5#+b
END FUNCTION
Программа 9_03.с
#include <stdio.h>
#include <conio.h>
#include <math.h>
double dif_time(int Yl,int Ml,double DTI,
int Y2,int M2,double DT2);
double JD(int У,int M,double DT);
main () {
int Y1,Y2,M1,M2;
double DT1,DT2;
clrscr();
printf("\ n Задайте год григорианского календаря : ");
scanf("ld",&Yl);
printf("\n Задайте месяц григорианского календаря : ");
scanf("%d",&Ml);
printf("\nЗадайте день и время : ");
scanf("%lf",&DTD;
printf("\n Задайте год григорианского календаря : ");
scanf("%d",SY2);
printf("\n Задайте месяц григорианского календаря : ");
scanf("%d",&M2);
printf("\n Задайте день и время : "};
scanf("%lf",&DT2);
printf("\n Интервал = %lf",dif_time(Y1,M1,DTI,Y2,M2,DT2));
getch(); }
/*----------------------------*/
double dif_time(int Yl,int Ml,double DTI, int Y2,int M2, double DT2)
/* Определение интервала времени между */
/* двумя григорианскими датами */
/* Y1,Y2 - годы М1,М2 - месяцы */
/* целые части DTI, DT2 - дни */
/* дробные части DTI, DT2 - время дня */ /***************************************/
return fabs(JD(Yl,Ml,DTl)-JD(Y2,M2,DT2));
}
/*---------------------------------------------------* /
double JD(int Y,int M, double DT) {
int a,b=0,m,y;
long c;
y=Y;
m=M;
if (M<3) { y--; m += 12; }
a=y/100;
if(Y+M/100.+DT/10000 > 1582.1015)b += 2-a+(int)(a/4.);
c=365.25*y;
if(y<0) c=365.25*y-0.75;
return c+(long) (30.6001* (m+1))+DT+1720994.5+b; }
Программа 9_03.pas
program gd_to_jd;
{Определение интервала времени между двумя датами григорианского календаря : (Y1,M1,DT1) и (Y2,M2,DT2) }
uses Crt; var
Yl,Ml,Y2,М2:integer;
DTI,DT2:double;
function JD(Y,M:integer;
DT:double):double;
var
a,b,mm,yy:integer;
c:longint;
begin
b:=0;
yy:=Y;
mm:=M;
if M<3 then begin yy:=yy-l;
mm:=mm+12; end;
a:=yy div 100;
if (Y+M/100.+DT/10000)>1582.1015 then b:=b+2-a+(a div 4};
c:=trunc(365.25*yy);
if yy<0 then c:=trunc(365.25*yy-0.75);
JD:=c+trunc(30.6001*(mm+1))+DT+1720994.5+b;
end;
function dif_time(Yl,Ml:integer;
DTI:double;
Y2,M2:integer; DT2:double):double;
{ Определение интервала времени между }
{ двумя григорианскими датами }
{ Y1,Y2 - годы М1,М2 - месяда }
{ целые части DTI, DT2 - дни }
{ дробные части DTI, DT2 - время дня } begin
dif_time:=abs(JD(Y1,M1,DT1)-JD(Y2,M2,DT2)) ;
end;
begin
clrscr;
write(' Задайте год григорианского календаря : ');
readln(Yl);
write(' Задайте месяц григорианского календаря : ');
readln(Ml);
write(' Задайте день и время : ');
readln(DTl);
write(' Задайте год григорианского календаря : ');
readln(Y2);
write(' Задайте месяц григорианского календаря : ');
readln(M2);
write(' Задайте день и время : ') ; readln(DT2);
writeln('Интервал = ',dif_time(Y1,M1,DT1,Y2,M2, DT2):10:0); readln; end.
Задание 9.04. День недели
Составить функцию week_day, определяющую день недели по дате григорианского календаря.
Совет 1 (общий)
Преобразуйте григорианскую дату в юлианский день и воспользуйтесь довольно очевидной формулой:
день недели=(JD+1.5) mod 7
В ее справедливости нетрудно убедиться, вспомнив, что понедельник 1 января условной начальной точки отсчета универсального времени (год 4712 до н. э.) начинался в момент JD=-0 . 5. Приведенная выше формула дает 0 для воскресенья, 1 —для понедельника, 2 — для вторника, ..., 6 — для субботы.
Совет 2 (общий)
Функция week_dayl построена на базе аналогичной фортрановской программы, и сфера ее применения распространяется на даты позднее 15.10.1582.
Программа 9_04.bas
DECLARE FUNCTION JD!(Y%,M%,DT!)
DECLARE FUNCTION WeekDay!(Y%,M%,D%)
REM Определение дня недели
CLS
INPUT "Задайте год григорианского календаря : ",Y%
INPUT "Задайте месяц григорианского календаря : ",М%
INPUT "Задайте день : ",D%
PRINT "день недели = ";WeekDay(Y%, M%, D%)
END
FUNCTION JD(Y%,M%,DT)
DIM a AS INTEGER, b AS INTEGER, mm AS INTEGER, yy AS INTEGER
DIM с AS LONG
b=0
yy=Y%
mm=M%
IF M%<3 THEN yy=yy-l: mm=ram+12
a=yy\100
IF Y%+M%/100!+DT/10000>1582.1015# THEN
b=b+2-a+a\4 END IF
c=INT(365.25*yy)
IF yy<0 THEN c=INT(365.25*yy-.75)
JD=c+INT(30.6001*(mm+1))+DT+1720994.5#+b
END FUNCTION
FUNCTION WeekDay(Y%,M%,D%)
' Определение дня недели
' Y - григорианский год
' М - григорианский месяц (1 - 12)
' D - день (1 - 31)
' Возвращаемое значение :
' 0 - воскр., 1 - понед., 2 - вторник,...
WeekDay=INT(JD(Y%,M%,D%+1.5)) MOD 7
END FUNCTION
Программа 9_04.с
#include <stdio.h>
#include <conio.h>
#include <math.h>
int week_day(int Y,int M,int D);
double JD(int Y,int M,double DT);
main() {
int Y,M,D,day;
clrscr();
printf("\nЗадайте год григорианского календаря : ") ;
scanf("%d",&Y);
printf("\nЗадайте месяц григорианского календаря : ");
scanf("%d",&M);
printf("\nЗадайте день : ") ;
scanf("%d",&D);
day=week_day (Y, M, D) ,-
printf("\пдень недели = %d",day) ;
getch();
}
/*--------------------------------*/
int week_day(int У,int M,int D)
/* Вычисление дня недели */
/* Возвращаемое значение : */
/* 0 - воскр., 1 - понед., 2 - вторник,... */
/************************************/
{
return (long)(JD(Y,M,(double)D)+1.5) % 7;
}
/*---------------------------------*/
double JD(int Y,int M,double DT) int a,b=0,m,y;
long c;
y=Y;
m=M;
if (M<3) { y--; m += 12; }
a=y/100;
if(Y+M/100.+DT/10000 > 1582.1015) b += 2-a+(int)(a/4.);
c=365.25*y;
if(y<0)c=365.25*y-0.75;
return c+(long)(30.6001*(m+1))+DT+1720994.5+b; }
Функция week_day1.с
int week_dayl( int Y, int M, int D)
{
/********************************/
/* Вычисление дня недели */
/* Возвращаемые значения: */
/* 1 - пон., 2 - вторник,..., 7 -воскр */
int q,m;
q=M+10;
m=(M-14)/12+Y;
return ((13*(q-(q/13)*12)-1)/5+D+77+5* (m%100) /4 +
m/400-(m/100)*2)%7; }
Программа 9_04.pas
program WeekDay;
{ Определение дня недели }
uses Crt;
var
Y,M,D,day:integer;
function JD(Y,M:integer; DT:double):double; var
a,b,mm,yy:integer;
с:longint; begin
b:=0;
yy:=Y;
mm:=M;
if M<3 then begin yy:=yy-l;
mm:=mm+12; end;
a:=yy div 100;
if (Y+M/100.+DT/10000)>1582.1015 then b:=b+2-a+(a div 4);
c:=trunc(365.25*yy);
if yy<0 then c:=trunc(365.25*yy-0.75) ;
JD:=c+trunc(30.6001*(mm+l))+DT+1720994.5+b;
end;
function week_day(Y,M,D:integer):integer;
{ Определение дня недели }
{ Y - григорианский год }
{ М - григорианский месяц (1-12) }
{ D - день (1 - 31) }
{ Возвращаемое значение : }
{ 0 - воскр., 1 - понед., 2 - вторник,... }
begin
week_day:=trunc(JD(Y,M,D+1.5)) mod 7; end;
begin
clrscr;
write(' Задайте год григорианского календаря : ') ;
readln(Y);
write(' Задайте месяц григорианского календаря : ') ;
readln(M);
write (' Задайте день : ');
readln(D);
day:=week_day(Y,M,D);
writeln('день недели = ',day);
readln; end.
Задание 9.05. Порядковый день в году
Составить функцию dat_to_ord, вычисляющую порядковый номер дня в году по его дате.
Совет 1 (общий)
Воспользуемся алгоритмом, описанным в книге Меёса. Для обычного года:
N=int(275*M/9)-2*int((М+9)/12)+D-30
Для високосного года:
N=int(275*M/9)-int((М+9)/12)+D-30
Программа 9_05.bas
DECLARE FUNCTION DatToOrd!(y%,M%,D%)
REM Определение порядкового дня в году по
REM текущей дате (у - год, m -месяц, d - день)
CLS
INPUT "Задайте год : ",у%
INPUT "Задайте месяц : ",М%
INPUT "Задайте день : ",D%
PRINT "Порядковый номер дня в году = ";
DatToOrd(у%,M%,D%)
END
FUNCTION DatToOrd(y%,M%,D%)
DIM a1 AS INTEGER, a2 AS INTEGER
al=(M%+9)\12
a2=INT(275!*M%/9!}-a1+D%
IF (y% MOD 400=0) OR ( (y MOD 4=0) AND (y MOD 100<>0) ) THEN DatToOrd=a2-30
ELSE DatToOrd=a2-al-30
END IF
END FUNCTION
Программа 9_05.c
#include <stdio.h>
#include <conio.h>
int dat_to_ord(int y,int m,int d) ;
main() {
int Y,M,D;
clrscr();
printf("\nЗадайте год : ");
scanf("%d",&Y);
printf("\nЗадайте месяц : ");
scanf("%d",&M);
printf("\nЗадайте день : ");
scanf("%d",&D) ;:
printf("\nПорядковый номер дня в году = %d", dat_to_ord(Y,M,D));
getch();
}
/*-----------------------------------------*/
int dat_to_ord(int y,int m,int d)
{
int a1,a2;
al=(m+9.0)/12.0;
a2=(275.0*m/9.0)-a1+d-30;
if((y%400==0)||((y%4==0)&&(y%100!=0)))
return a2;
return a2-a1; }
Программа 9_05.pas
program ord day;
изез Crt; var
Y,M,D:integer;
function dat_to_ord(y,m,d:integer):integer; {
Определение порядкового дня в году по текущей дате (у - год, m - месяц, d - день) } var
al,a2:integer; begin
al:=(m+9) div 12;
a2:=trunc(275.0*m/9.0)-al+d-30;
if((y mod 400 = 0) OR {(y mod 4=0) AND (y mod 100 <>0))) then dat_to__ord: =a2
else dat_to_ord:=a2-al;
end;
begin
clrscr;
write('Задайте год : ');
readln(Y);
write('Задайте месяц : ');
readln(M);
write('Задайте день : ');
readln(D);
writeln('Порядковый номер дня в году = ', dat_to_ord(Y,M,D));
readln;
end.
Задание 9.06. Восстановление даты
Составить процедуру month_day, вычисляющую номера месяца (M) и дня (D) по порядковому номеру (N) дня в году.
Совет 1 (общий)
Воспользуемся алгоритмом, описанным в книге Меёса. Положим, что А = 1889 для обычного года и А = 1523—для високосного.
Вычислим :
B=int((N+A-122.1)/365.25)
C=N+A-int(365.25*B)
E=int(C/30.6001)
M=E-1 при Е<13.5
M=E-13 при Е>13.5
D=C-int(30.6001*E)
Программа 9_06.bas
DECLARE SUB MonthDay(Y%,OrdDay%,M%,D%)
RЕМ Восстановление даты по порядковому дню года
CLS
INPUT "Задайте год : ",Y%
INPUT "Задайте порядковый номер дня в году : ",OrdDay%
MonthDay Y%,OrdDay%,М%,D%
PRINT "Ему соответствует месяц = ",М%;" и день = ";D%
END
SUB MonthDay(Y%,OrdDay%,M%,D%)
' Восстановление месяца и дня в году Y%
' по порядковому номеру дня ord_day%
' М% - сюда засылается номер месяца
' D% - сюда засылается номер дня месяца
DIM A AS INTEGER, В AS INTEGER, С AS INTEGER, E AS INTEGER
A=1889
IF (Y% MOD 400=0)OR((Y% MOD 4=0)AND(Y% MOD l00<>0) ) THEN A=1523
B=INT((OrdDay%+A-122.1)/365.25)
C=OrdDay%+A-INT(365.25*B)
E=INT(C/30.6001)
IF E<13.5 THEN M%=E-1 ELSE M%=E-13'
D%=C-INT(30.6001*E)
END SUB
Программа 9_06.с
#include <stdio.h> ,
#include <conio.h>
#include <math.h>
void month_day(int Y,int ord_day,int *M,int *D);
main() {
int Y,M, D,ord_day;
clrscr();
printf("\n Задайте год : ");
scanf("%d",&Y);
printf("\n Задайте порядковый номер дня в году : ");
scanf("%d",&ord_day);
month_day(Y,ord_day,&M, &D);
printf("\nЕму соответствует месяц = %d и день = %d",M,D);
getch();
}
/*-------------------------------------*/
void month_day(int Y,int ord_day,int *M,int *D)
/*************************************/
/* Восстановление месяца и дня в году Y */
/* по порядковому номеру дня ord_day */
/* М - сюда засылается номер месяца */
/* D - сюда засылается номер дня месяца */
/****************************************/
{
int A=1889,B,C,E;
if((Y%400==0)||((Y%4==0)&&(Y%100!=0))) A=1523;
B=(ord_day+A-122.1)/365.25;
C=ord_da>y+A-floor (365. 25*B) ;
E=C/30.6001;
if(E<13.5) *M=E-1; else *M=E-13;
*D=C-floor(30.6001*E); }
Программа 9_06.pas
program ord_to_dat;
uses Crt;
var
Y,M,D,ord_day:integer;
procedure month_day(Y,ord_day:integer;var M,D:integer);
{ Восстановление месяца и дня в году Y }
{ по порядковому номеру дня ord_day }
{ М - сюда засылается номер месяца }
{ D - сюда засылается номер дня месяца } var
А,В, С,Е:integer; begin
А:=1889;
if(Y mod 400 = 0) OR ((Y mod 4 = 0)AND(Y mod 100 <>0))) then A:=1523;
B:=trunc((ord_day+A-122.1)/365.25) ;
C:=ord_day+A-trunc(365.25 * B);
E:=trunc(C/30.6001);
if(E<13.5) then M:=E-1 else M:=E-13;
D:=C-trunc(30.6001*E); end; begin
clrscr;
write('Задайте год : ');
readln(Y);
write ('Задайте порядковый номер дня в году : ');
readln(ord_day);
month_day(Y,ord_day,M,D);
writeln('Eмy соответствует месяц = ',М, ' и день = ',D);
readln; end.
Задание 9.07. Количество дней в месяце
Составить функцию max_day, определяющую количество дней по номеру месяца.
Совет 1 (общий)
Наверное, самый простой алгоритм основан на выборке нужного числа из предварительно подготовленного массива с учетом коррекции количества февральских дней в високосном году. Високосный год должен делиться без остатка на 400 или делиться на 4, но не делиться на 100.
Программа 9_07.bas
DECLARE FUNCTION MaxDay!(Y%,M%)
REM Определение количества дней в месяце
DATA 31,28,31,30,31,30,31,31,30,31,30,31
DIM SHARED DAYS(1 TO 12)
FOR J=l TO 12: READ DAYS(J): NEXT J
CLS
INPUT "Задайте год : ",Y%
INPUT "Задайте месяц : ",M%
PRINT "Число дней в этом месяце = ";
MaxDay (Y%,M%)
END
FUNCTION MaxDay(Y%,M%)
MaxDay=DAYS(M%)
IF M%<>2 THEN EXIT FUNCTION
IF (Y% MOD 400=0)OR((Y% MOD 4=0)AND(Y% MOD 100<>0) ) THEN MaxDay=29
END IF END FUNCTION
Программа 9_07.с
#include <stdio.h>
#include <conio.h>
int max_day(int Y, int M);
main() . {
int Y,M;
printf("\n Задайте год : ");
scanf("%d",&Y);
printf("\3адайте месяц : ");
scanf("%d",&M);
printf("\n Число дней в этом месяце = %d",max_day(Y,M));
getch();
}
/*--------------------------------------*/
int max_day(int Y, int M)
{ int days[]={31,28,31,30,31,31,30,31,30,31,30,31);
if(M != 2) return days[M-l];
if{(Y%400==0)||((Y%4==0)&&(Y%100!=0))}
return 29;
return 28; }
Программа 9_07.pas
program days_in_month;
{ Определение количества дней в месяце }
var
Y,M:integer;
function max_day(Y,M:integer):integer; const
days:array[1..12] of byte=(31,28,31,30,31,30, 31, 31, 30, 31, 30, 31);
begin
max_day:=days[M];
if(M<>2) then exit;
if((Y mod 400=0)OR((Y mod 4=0)AND(Y mod l00<>0) ) ) then
max_day:=29; end; begin
write('Задайте год : ');
readln(Y);
write('Задайте месяц : ');
readln(M);
writeln('Число дней в этом месяце = ',max_day(Y,M));
readln; end.
Задание 9.08. Календарь
Составить процедуру calendar, отображающую на экране дисплея календарь на заданный месяц любого года.
Совет 1 (общий)
Для понимания приведенных ниже программ достаточно разобраться с тремя моментами.
Во-первых, календарь любого месяца можно разместить в таблице, содержащей 7 строк (по числу дней недели) и 6 столбцов. В худшем варианте 1-е число
месяца выпадает на воскресенье, занимая тем самым последнюю клетку 1-го столбца, а два последних дня месяца — 30 и 31 — на понедельник и вторник последнего столбца. Двумерную таблицу календаря удобнее представить в виде одномерного массива из 42 элементов.
Во-вторых, для определения местоположения 1-го дня месяца мы можем обратиться к функции week_day.
Наконец, с помощью функции max_day мы можем определить число дней в заданном месяце. После этого остается очистить нулями массив из 42 элементов и расписать его с нужного места последовательными днями месяца. А затем отобразить на экране ненулевые элементы в соответствующих позициях экрана.
Программа 9_08.bas
DECLARE SUB calendar(Y%,M%)
DECLARE FUNCTION JD!(Y%,M%,DT!)
DECLARE FUNCTION WeekDay!(Y%,M%,D%)
DECLARE FUNCTION MaxDay!(Y%,M%)
REM Программа вывода календаря на любой месяц
DATA 31,28,31,30,31,30,31,31,30,31,30,31
DIM SHARED DAYS(1 TO 12)
FOR j=l TO 12: READ DAYS(j): NEXT j
CLS
INPUT "Задайте год : ",Y%
INPUT "Задайте месяц : ",M4
calendar Y%,M%
END
SUB calendar(Y%,M%)
DIM i AS INTEGER, j AS INTEGER, k AS INTEGER, q AS INTEGER
DIM a(42),b$<7)
b$(0}="понедельник": b$(1)="вторник ": b$(2)="среда
b$(3)="четверг ": b$(4)="пятница ": b$(5)="суббота
b$(6)="воскресенье"
CLS
PRINT "Календарь на ";М%;" месяц ";Y%;" года"
i=WeekDay(Y%,M%,l)
IFi=0 THEN i=7
q-MaxDay(Y%,M%)
FOR j=0 TO 41: a(j)=0: NEXT j
k=l
FOR j=i-l TO q+i-2: a(j)=k: k=k+l: NEXT j
FOR j=0 TO 6
LOCATE j+3,10: PRINT b$(j);
k=0
WHILE k<=35
IF a(k+j)<>0 THEN
PRINT USING "####";a(k+j); ELSE PRINT " ";
END IF k=k+7
WEND NEXT j END SUB
FUNCTION JD(Y%,M%,DT)
DIM a AS INTEGER, b AS INTEGER, mm AS INTEGER, yy AS INTEGER
DIM с AS LONG
b=0
yy=Y%
mm=M%
IF M%<3 THEN yy=yy-l: mm=mm+12
a=yy\100
IF Y%+M%/100!+DT/10000>1582.1015# THEN b=b+2-a+a\4
END IF
c=INT(365.25*yy) IF yy<0 THEN c=INT(365.25*yy-.75)
JD=c+INT(30.6001*(mm+1))+DT+1720994.5#+b END FUNCTION
FUNCTION MaxDay(Y%,M%)
MaxDay=DAYS(M%)
IF M%<>2 THEN EXIT FUNCTION
IF (Y% MOD 400=0)OR((Y% MOD 4=0)AND(Y% MOD l00<>0) ) THEN MaxDay=29
END IF END FUNCTION
FUNCTION WeekDay(Y%,M%,D%) dl!=D%+1.5
WeekDay=INT(JD(Y%,M%,dl!)) MOD 7 END FUNCTION
Программа 9_08.с
#include <stdio.h>
#include <conio.h>
void calendar(int Y,int M);
int week_day(int Y,int M,int D) ;
double JD(int Y,int M,double DT);
int max_day(int Y,int M);
main() {
int Y,M;
clrscr();
printf("Задайте год : ");
scanf("%d",&Y);
printf("Задайте месяц : ");
scanf("%d",&M);
calendar(Y,M);
getch(};
}
/*-------------------------------------------*/
void calendar'(int Y, int M) {
int a[42],i, j,k,q;
char *b[7]={"понедельник",
"вторник ",
"среда ",
"четверг ",
"пятница ",
"суббота ",
"воскресенье"}; clrscr();
printf("\ t Календарь на Id месяц %d года",М,У);
i=week_day(Y,M,1); /* определение дня недели для 1.M.Y */
if(i==0)i=7;
q=max day(Y,M); /* определение количества дней в месяце */
for(j=0; j<42; j++) a[j]=0;
for(j=i-l,k=l;
j<q+i-l; j++,k++) a[j]=k;
for(j=0; j<7; j++) {
gotoxy{10,j+3);
printf("%s",b[j]);
for(k=0; k<=35; k+=7)
if(a[k+j] != 0) printf("%4d",a[k+j]);
else printf("%4c",' '); }
return;
}
/*----------------------------------------*/
double JD(int Y,int M,double DT)
int a,b=0,m,y;
long c;
y=Y;
m=M;
if (M<3) { y--; m += 12; }
a = y/100;
if(Y+M/100.+DT/10000 > 1582.1015} b += 2-a+(int)(a/4.);
c=365.25*y; if(y<0)c=365.25*y-0.75;
return c+(long)(30.6001*(m+1))+DT+1720994.5+b;
}
/*---------------------------------*/
int week_day(int Y,int M,int D)
{
int q,m;
q = M+10;
m = (M-14)/12 + Y;
return
((13*(q-(q/13)*12)-1)/5+D+77+5*
(m%100)/4+m/400-(m/100)*2)%7;
}
/*-----------------------------------*/
int max_day(int Y,int M)
{ int days[]={31,28,31,30,31,31,30,31,30,31,30,31};
if(M != 2) return days[M-l];
begin
max_day:=days[M];
if (M=2)and((Y mod 400=0) or ( (Y mod 4=0) and (Y mod 100<>0) ) ) then
max_day:=2 9; end;
procedure calendar(Y,M:integer);
var
i,j,k,q:integer; a:array [0..41] of byte;
const
b:array [0..6] of string=('понедельник',
'вторник ', 'среда ',
'четверг ',
'пятница ',
'суббота ', 'воскресенье '};
begin clrscr;
write(' Календарь на ',М, ' месяц ',Y, ' года');
i:=week_day(Y,M,1);
if 1=0 then i:=7;
q:=max_day(Y,M);
for j:=0 to 41 do
a[j]:=0; k:=l;
for j:=i-l to q+i-2 do begin
a[j]:=k;
inc(k);
end;
for j:=0 to 6 do begin
gotoxy(10, j+3) ;
write(b[j]); k:=0;
while k<= 35 do begin;
if a[k+j] о 0 then
write(a[k+j]:4)
else write(' ':4); k:=k+7;
end;
end;
end;
begin {main}
clrscr;
write('Задайте год : ');
readln(Y);
write('Задайте месяц : ');
readln(M);
calendar(Y,M);
readln; end.
Задание 9.09. Преобразования времени суток
Составить процедуры упаковки и распаковки времени суток. Исходными данными для их работы должны быть либо показания часов (H — часы, M -минуты, S — секунды), либо часть суток, представленная вещественным числом t (0<= t <= 1).
Программа 9_09.bas
DECLARE SUB UnpackTime(T!,H%,M%,S%)
DECLARE FUNCTION PackTime!(H%,M%,S%)
КЕМ Упаковка и распаковка показаний часов
CLS
Н%=18: М%=0: S%=0
T=PackTime(H%,М%,S%)
PRINT USING "##:##:## = ###.##";H%;M%;S%;T
T= 5
UnpackTime T,H%,M%,S%
PRINT USING "##:##:## = ###.##";H%;M%;S%;T
END
FUNCTION PackTime(H%,M%,S%)
' Упаковка времени - перевод часов (Н%)
' минут (М%) и секунд (S%) в часть суток
PackTime = (Н% * 3600! + м% * 60 + S%) / 86400!
END FUNCTION
SUB UnpackTime(Т,H%,M%,S%)
' Распаковка времени - перевод части суток
' в часы (Н%), минуты (М%) и секунды (S%)
t1!=T*86400 H%=INT(tl1/3600! )
t1!=t1!-3600!*H% M%=INT(t1!/60!)
S%=INT(t1!-60!*M%)
END SOB
Программа 9_09.c
#include <stdio.h>
#include <conio.h>
double pack_time(int H, int M,int S) ;
void unpack_time(double t,int *H,int *M,int *S);
main() {
int H=18,M=0,S=0;
double T;
clrscr();
T=pack_time(H,M,S);
printf("\n%2d:%2d:%2d=%f",H,M,S,T);
T=0.75;
unpack_time(T,&H, &M,&S);
printf("\n%2d:%2d:%2d=%f",H,M,S,T);
getch();
}
/*----------------------------------------*/
double pack_time(int H,int M,int S)
/****************************************/
/* Упаковка времени - перевод часов (Н) .*/
/* минут (М) и секунд (S) в часть суток */
/****************************************/
{
return (H*3600.0+M*60+S)/86400.0; }
/*--------------------------------------*/
void unpack_time(double t,int *H,int *M,int *S)
/* Распаковка времени - перевод части суток */
/* в часы (Н), минуты (М) и секунды (S) */
{
double tl;
t1=t*86400;
*H=t1/3600.0;
t1=t1-3600.0*(*H);
*M=t1/60.0;
*S=t1-60.0*(*M);
}
Программа 9_09.pas
program pack_unpack;
uses Crt;
var
H,M,S:integer;
Т:double;
function pack_time(H,M,S:integer):double;
{ Упаковка времени - перевод часов (Н)минут (М) и секунд (S) в часть суток } begin
pack_time:=(H*3600.0+M*60+S)/86400.0;
end;
procedure unpack_time(t:double;var H,M,S:integer);
{ Распаковка времени - перевод части суток
в часы (Н), минуты (М) и секунды (S) }
var
t1:double; begin
t1:=t*86400;
H:=trunc(t1/3600.0) ;
t1:=t1-3600.0*H;
M:=trunc(t1/60.0);
S:=trunc(t1-60.0*M);
end;
begin {main}
clrscr;
H:=18; M:=0; S:=0;
T:=pack_tiine(H,M,S) ;
writeln(H:2,': ',M:2, ': ',S:2, ' =',T:6:2);
T:=0.5;
unpack_time(T,H,M,S);
writeln(H:2, ': ',M:2, ': ',S:2, ' =',T:6:2);
readln;
end.