Практика программирования (Бейсик, Си, Паскаль)

       

Составить функцию 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.

Содержание раздела