русс | укр

Языки программирования

ПаскальСиАссемблерJavaMatlabPhpHtmlJavaScriptCSSC#DelphiТурбо Пролог

Компьютерные сетиСистемное программное обеспечениеИнформационные технологииПрограммирование

Все о программировании


Linux Unix Алгоритмические языки Аналоговые и гибридные вычислительные устройства Архитектура микроконтроллеров Введение в разработку распределенных информационных систем Введение в численные методы Дискретная математика Информационное обслуживание пользователей Информация и моделирование в управлении производством Компьютерная графика Математическое и компьютерное моделирование Моделирование Нейрокомпьютеры Проектирование программ диагностики компьютерных систем и сетей Проектирование системных программ Системы счисления Теория статистики Теория оптимизации Уроки AutoCAD 3D Уроки базы данных Access Уроки Orcad Цифровые автоматы Шпаргалки по компьютеру Шпаргалки по программированию Экспертные системы Элементы теории информации

Биоритмы


Дата добавления: 2015-06-12; просмотров: 746; Нарушение авторских прав


Давно известно, что творческая и физическая активность человека не остается постоянной, циклически меняется, причем периодичность ее изменения приблизительно согласуется с периодом вращения Луны вокруг Земли. Существует теория, согласно которой физическая, эмоциональная и интеллектуальная активность человека подчиняется соответствующим биоритмам. Каждый биоритм представляет собой синусоиду со строго постоянным периодом, причем для каждого биоритма существует свой период. В отдельные дни все три биоритма человека могут достигнуть своего максимума и тогда человек испытывает подъем творческих и физических сил, в такие дни у него все спорится, он легко решает проблемы, которые в другое время ему решить гораздо сложнее. Точно также существуют и «черные» дни, соответствующие спаду всех трех биоритмов.

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

Алгоритм программы можно укрупнено записать следующим образом:

  • ввести дату рождения и текущую дату, проконтролировать их правильность и непротиворечивость;
  • вычислить количество дней между двумя датами, чтобы определить фазу синусоид для текущей даты;
  • вычислить количество дней от текущей даты до даты ближайшего пика биоритмов и даты ближайшего спада;
  • определить и напечатать обе даты.

Будем считать, что каждое из перечисленных действий реализуется в отдельной процедуре, тогда начальный вариант программы будет таким:

Procedure InputDates(var dO,mO,yO,d,m,y: Integer);

{Вводит дату рождения и текущую дату. Контролирует правильность дат и их непротиворечивость (текущая дата должна быть позже даты рождения) }



begin {InputDates}

end; {InputDates}

{..........................}

Procedure Get_count_pf_days (dO,mO,yO,d,m,y: Integer;

var days: Integer);

{Определяет полное количество дней, прошедших от одной даты до другой}

begin {Get_count_of_days}

end; {Get_count_of_days}

{--------------------------}

Procedure FindMaxMin (var dmin,dmax: Integer; days: Integer);

{Ищет критические дни}

begin {FindMaxMin}

end; {FindMaxMin}

{--------------------------}

Procedure WriteDates ( dmin , dmax , days : Integer);

{Определяет критические даты по количеству дней, прошедших от

момента рождения, и выдает эти даты на экран}

begin {WriteDates}

end; {WriteDates}

{--------------------------}

var

d0,d , {Дни рождения и текущий}

m0,m, {Месяцы рождения и текущий}

у0,у, {Годы рождения и текущий}

dmin, {Наименее благоприятный день}

dmax, {Наиболее благоприятный день}

days: Integer; {Количество дней от рождения}

begin {Главная программа}

Input-Dates (d0,m0,y0,d,m,y) ;

Get_numbers_of_days (d0,m0,y0,d,m,y,days) ;

FindMaxMin (dmin, dmax, days) ;

WriteDates (dmin, dmax, days)

end .

Начинаем детализацию программы. Прежде всего подумаем, как по двум датам вычислить разделяющее их количество дней? Если вспомнить, что следует учитывать неодинаковое количество дней по месяцам года, а также 29 февраля для високосных лет, то ответ на этот вопрос окажется не таким уж простым. Предлагаемый алгоритм подсчета количества дней заключается в вычислении количества дней от даты рождения до конца месяца, а затем и года рождения, количества дней, от начала текущего года до текущего месяца и текущей даты, а также - в подсчете количества полных лет, разделяющих обе даты. Количество лет затем легко пересчитывается в количество дней с учетом длины года (365 дней для обычных и 366 дней для високосных лет). Это очень прямолинейный алгоритм, но, откровенно говоря, мне не пришло в голову ничего другого. Возможно, существует более изящный способ подсчета и Вы его знаете, тогда программная реализация будет другой.

Упростить алгоритм можно за счет создания и использования массива из 12 целых чисел, содержащего количества дней по месяцам невисокосного года, т.е. 31, 28, 31, 30 и т.д. Этот массив (назовем его SIZE_OF_MONTH - длина _месяца) можно использовать и для обратной задачи, т.е. для определения даты критических дней, а также дляпроверки правильности вводимых дат. Таким образом, массив SIZE__OF_MONTH будет использоваться сразу в трех процедурах. Сделаем его глобальным, для чего его описание поместим перед описанием процедур:

const

Size_of_Month: array - [1. .12] of Byte =

(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);

{--------------------------}

Procedure InputDates (var d0,m0,y0,d,m,y: Integer);

.........

Поскольку описание массива размещается до описания процедур, он становится доступным внутри каждой из процедур и служит для них глобальным. В отличие от этого все константы и переменные, объявляемые внутри некоторой процедуры, являются локальными и могут использоваться только в этой процедуре.

С учетом сказанного напишем следующий начальный вариант программной реализации процедуры INPUTDATES:

Procedure InputDates(var d0,m0,y0,d,m,y: Integer);

{Вводит дату рождения и текущую дату. Контролирует правиль-

ность дат и их непротиворечивость (текущая дата должна быть

позже даты рождения)}

var

correctly: Boolean; {Признак правильного ввода}

begin {InputDates}

repeat

{Вводим и контролируем дату рождения d0,m0,y0.}

{Вводим и контролируем текущую дату d,m,y.}

{Проверяем непротиворечивость дат:}

correctly := у > у0; if not correctly and (у = y0) then

begin

correctly := m > m0;

if not correctly and (m = m0) then

correctly := d>=d0

end

until correctly

end; {InputDates}

В этой процедуре дважды выполняется одно и то же алгоритмическое действие (ввод и контроль даты). Это действие можно вынести в отдельную внутреннюю процедуру с именем INPDATE, тогда получим следующий окончательный вариант:

Procedure InputDates(var d0,m0,y0,d,m,y : Integer);

{Вводит дату рождения и текущую дату. Контролирует правильность дат и их непротиворечивость (текущая дата должна быть позже даты рождения)}

var

correctly: Boolean; {Признак правильного ввода}

{--------------------------}

Procedure InpDate (text: String; var d,m,y: Integer);

{Выводит приглашение TEXT, вводит дату в формате ДД ММ ГГГГ и

проверяет ее правильность}

const

YMIN = 1800; {Минимальный правильный год}

YМАХ = 2000; {Максимальный правильный год}

begin {InpDate}

repeat

Write (text);

ReadLn (d,m,y) ;

correctly := (y >= YMIN) and (Y <= YMAX) and (m >= 1)

and (m <= 12) and (d > 0) ; if correctly then

if (m = 2) and (d = 29) and (y mod 4=0) then

{Ничего не делать: это 29 февраля високосного года!}

else

correctly := d <= Size_of_Month[m] ;

if not correctly then

WriteLn (' Ошибка в дате!')

until correctly

end; {InpDate}

{--------------------------}

begin {InputDates}

repeat

InpDate (' .Введите дату рождения в формате ДД ММ ГГГГ:',d0,m0,y0) ;

InpDate (' Введите текущую дату: ',d,m,y);

{Проверяем непротиворечивость дат:}

correctly := у > у0; if not correctly and (y = y0) then

begin

correctly := m > m0;

if not correctly and (m = m0) then

correctly := d >= d0

end

until correctly

end; {InputDates}

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

  • месячный младенец (год и месяц обеих дат одинаков): количество дней находится простым вычитанием двух чисел;
  • годовалый младенец (год обеих дат совпадает): количество дней = (остаток дней в месяце рождения) + (количество дней в текущем месяце) + (количество дней в месяцах, разделяющих обе даты);
  • общий вариант (отличаются года): количество дней = (количество дней от даты рождения до конца года) + (количество дней в разделяющих даты годах) + (количество дней от начала текущего года до текущей даты).

С учетом этого составим начальный вариант программной реализации процедуры

GET_NUMBERS_OF_DAYS :

Procedure Get_numbers_of_days (d,m,y,d,m,y: Integer;

var days: Integer);

{Определение полного количества дней, прошедших от одной даты до другой }

{--------------------------}

Procedure Variant2;

{Подсчет количества дней в месяцах,разделяющих обе даты}

begin {Variant2}

end; {Variant2}

{--------------------------}

Procedure Variant3 ;

{Подсчет количества дней в месяцах и годах, разделяющих обедаты}

begin {Variant3}

end; {Variant3}

{--------------------------}

begin {Get_numbers_of_days}

if (y = y0) and (m = m0) then {Даты отличаются только днями: }

days := d - d0

else {Даты отличаются не только днями:}

begin

days := d + Size_of_Month [m0] - d0;

{Учитываем количество дней в текущем месяце и количество дней до конца месяца рождения}

if (y0 mod 4=0) and (m0 = 2) then

inc(days); {Учитываем високосный год}

if у = y0 then

Variant2 {Разница в месяцах одного и того же года}

else

Variant3 {Даты отличаются годами}

end

end; {Get_numbers_of_days}

В этом фрагменте используется способ связи вспомогательных процедур VARIANT2 и VARIANT3 с основной процедурой через глобальные переменные, которыми являются параметры обращения к основной процедуре. Вспомогательные процедуры удобнее всего реализовать на основе циклов WHILE:

Procedure Variant2 ;

{Подсчет количества дней в месяцах, разделяющих обе даты }

var

mm : Integer;

begin {Variant2}

mm : = m0 ;

while mm < m do

begin

days := days + Size_of_Month [mm] ;

if (mm = 2) and (y0 mod 4=0) then

inc (days) ;

inc (mm)

end

end; {Variant2}

{--------------------------}

Procedure Variant3;

{Подсчет количества дней в месяцах и годах, разделяющих обедаты }

var

mm/ УУ : Integer;

begin {Variant3}

mm : = m0 + 1 ;

while mm <= 12 do {Учитываем остаток года рождения:}

begin

days := days+Size_of_Month [mm] ;

if (mm = 2) and (y0 mod 4=0) then

inc (days) ;

inc (mm)

end ;

yy := y0 + 1;

while yy < у do {Прибавляем разницу лет:}

begin

days : = days + 365;

if yy mod 4=0 then

inc (days) ;

inc (yy)

end;

mm : = 1 ;

while mm < m do {Прибавляем начало текущего года:}

begin

days := days + Size_of_Month [mm] ;

if (y mod 4=0) and (mm = 2) then

inc (days) ;

inc (mm)

end

end; {Variant3}

В процедуре FINDMAXMIN осуществляется поиск критических дней, т.е. ближайших к текущей дате дней, для которых все три биоритма достигают своего максимума и минимума. Предполагается, что биоритмы изменяются по законам синуса от количества прожитых дней с периодами ТF, ТE и TI соответственно для физической, эмоциональной и интеллектуальной активности человека. В программе приняты следующие периоды (в днях):

Знакомство с языком Турбо Паскаля

TF= 23.6884

ТЕ= 28.4261

TI= 33.1638

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

Procedure FindMaxMin(var dmin,dmax: Integer; days: Integer);

{Поиск критических дней}

const

TF = 2*3.1416/23.6884;{Период физической активности}

ТЕ = 2*3.1416/28.4261;{Период эмоциональной активности}

TI = 2*3.1416/33.1638;{Период интеллектуальной активности}

INTERVAL =30; {Интервал прогноза}

var

min, {Накапливает минимум биоритмов}

max, {Накапливает максимум биоритмов}

x : Real; {Текущее значение биоритмов}

i : Integer;

begin {FindMaxMin}

max := sin(days*TF)+sin(days*TE)+sin(days*TI);

min := max; {Начальное значение минимума и максимума равнозначению биоритмов для текущего дня}

dmin := days;

dmax := days;

for i := 0 to INTERVAL do

begin

x := sin((days+i)*TF) + sin((days+i)*TE) +sin((days+i)*TI);

if x > max then

begin

max : = x;

dmax : = days + i

end

else if x < min then

begin

min := x;

dmin := days + i

end

end;

end; {FindMaxMin}

При разработке алгоритма процедуры WRITEDATES, с помощью которой на экран выводится результат работы программы, учтем, что основные сложности будут связаны с определением новой даты по начальной дате и количеству прошедших дней. Этот насчет будет повторяться дважды - для даты пика и даты спада биоритмов, поэтомуего следует вынести в отдельную процедуру WRITEDATES. Кроме того, вряд ли Вы откажетесь от возможности вывода на экран дополнительной информации о том, сколько полных дней, часов, минут и секунд разделяют дату рождения человека и текущую дату. Однако реализация этого вывода не столь проста, как это может показаться на первый взгляд. Дело в том, что диапазон возможных значений данных типа INTEGER составляет от -32768 до +32767. Средняя продолжительность жизни человека - около 70 лет, т.е. 25550 дней. Это значение еще можно представить в Переменной типа INTEGER, однако часы, минуты и тем более секунды средней продолжительности жизни далеко превышают этот диапазон. Чтобы получить вывод достоверных данных, необходимо расширить диапазон значений целых чисел. Для этого в Турбо Паскале предусмотрен специальный тип данных LONGINT («длинный» целый), имеющий диапазон значений от -2147483648 до +2147483647 (см. гл. 4). Поэтому в процедуре WRITEDATES следует предусмотреть вспомогательную переменную этого типа, присвоить ей значение переменной DAYS и уже затем использовать «длинную» переменную для вычисления (и вывода) часов, минут, секунд. В результате начальный вариант процедуры WRITEDATES может быть таким:

Procedure WriteDates (dmin,dmax,days : Integer);

{Определение и вывод дат критических дней. Вывод дополнительной информации о количестве прожитых дней, часов, минут и секунд }

{---------------------}

Procedure WriteDate (text : String; dd : Integer);

{Определение даты для дня DD от момента рождения. В глобальных переменных d, m и у имеется текущая дата, в переменной DAYS -количество дней, прошедших от момента рождения до текущей даты.Выводится сообщение TEXT и найденная дата в формате ДД-МЕС-ГГГГ}

begin {WriteDate}

end; {WriteDate}

{---------------------}

var

LongDays: Longlnt; {"Длинная" целая переменная для часов,минут и секунд }

begin {Wri teDates}

LongDays : = days ;

WriteLn( 'Прошло: ', LongDays,' дней, ' , longDays*24, ' часов, ', LongDays*24*60, ' минут, ', LongDays*24*60*60, ' секунд');

WriteDate ( 'Наименее благоприятный день: ', drain);

WriteDate ( 'Наиболее благоприятный день: ',dmax)

end; {WriteDates}

Реализация процедуры WRITEDATE не вызывает особых сложностей:

Procedure WriteDate (text: String; dd: Integer);

const

Names_of_Monthes : array [1..12] of String [3] =('янв','фев','мар','апр','мая', 'июн','июл','авг','сен','окт', 'ноя','дек');

var

d0,m0,y0,ddd : Integer;

begin {WriteDate}

d0 := d;

m0 := m;

y0 : = y;

ddd := days;

while ddd<>dd do begin

inc(d0); {Наращиваем число}

if (y0 mod 4 <> 0) and (d0 > Size_of_Month[m0]) or(y0 mod ,4=0) and (d0=30) then

begin {Корректируем месяц}

d0 := 1;

inc(m0);

if m0 = 13 then {Корректируем год}

begin

m0 := 1;

inc(y0)

end

end;

inc(ddd)

end;

WriteLn(text,d0,'-',Names_of_Monthes[m0] ,'-',y0)

end; {WriteDate}

Собрав воедино отдельные части, получим полный текст программы (прил.5.2), предназначенной для определения биоритмов.



<== предыдущая лекция | следующая лекция ==>
Вычисление дня недели | Игра ним


Карта сайта Карта сайта укр


Уроки php mysql Программирование

Онлайн система счисления Калькулятор онлайн обычный Инженерный калькулятор онлайн Замена русских букв на английские для вебмастеров Замена русских букв на английские

Аппаратное и программное обеспечение Графика и компьютерная сфера Интегрированная геоинформационная система Интернет Компьютер Комплектующие компьютера Лекции Методы и средства измерений неэлектрических величин Обслуживание компьютерных и периферийных устройств Операционные системы Параллельное программирование Проектирование электронных средств Периферийные устройства Полезные ресурсы для программистов Программы для программистов Статьи для программистов Cтруктура и организация данных


 


Не нашли то, что искали? Google вам в помощь!

 
 

© life-prog.ru При использовании материалов прямая ссылка на сайт обязательна.

Генерация страницы за: 3.382 сек.