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

       

Составить функцию JD, вычисляющую юлианскую


Задание 9.01. Вычисления юлианских дат

Составить функцию JD, вычисляющую юлианскую дату по году (Y), номеру месяца (м), номеру дня и значению времени, заданным в виде вещественного числа от (целая часть от — порядковый номер дня в месяце, дробная часть от — часть суток, прошедшая после полуночи). Проверки на правильность задания исходной информации исключены, чтобы не загромождать текст программы.

Совет 1 (общий)

Составить функцию JD, вычисляющую юлианскую
По результатам довольно обширного численного эксперимента мы выяснили, что наиболее точный алгоритм представлен формулами Меёса. Поэтому тексты приводимых ниже программ используют алгоритм 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 (общий)

Составить функцию JD, вычисляющую юлианскую
Преобразуйте даты григорианского календаря и найдите разницу между соответствующими юлианскими датами. Чтобы не выяснять, какая из дат является предшествующей, можно найти модуль разности.

Программа 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, вычисляющую юлианскую
Преобразуйте григорианскую дату в юлианский день и воспользуйтесь довольно очевидной формулой:

день недели=(JD+1.5) mod 7

В ее справедливости нетрудно убедиться, вспомнив, что понедельник 1 января условной начальной точки отсчета универсального времени (год 4712 до н. э.) начинался в момент JD=-0 . 5. Приведенная выше формула дает 0 для воскресенья, 1 —для понедельника, 2 — для вторника, ..., 6 — для субботы.

Совет 2 (общий)

Составить функцию JD, вычисляющую юлианскую
Функция 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 (общий)

Составить функцию JD, вычисляющую юлианскую
Воспользуемся алгоритмом, описанным в книге Меёса. Для обычного года:

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 (общий)

Составить функцию JD, вычисляющую юлианскую
Воспользуемся алгоритмом, описанным в книге Меёса. Положим, что А = 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 (общий)

Составить функцию JD, вычисляющую юлианскую
Наверное, самый простой алгоритм основан на выборке нужного числа из предварительно подготовленного массива с учетом коррекции количества февральских дней в високосном году. Високосный год должен делиться без остатка на 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 (общий)

Составить функцию JD, вычисляющую юлианскую
Для понимания приведенных ниже программ достаточно разобраться с тремя моментами.

Во-первых, календарь любого месяца можно разместить в таблице, содержащей 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.

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