Отправляет email-рассылки с помощью сервиса Sendsay

Всё о работе в Интернет

  Все выпуски  

Занятие 13.


Сегодня, уважаемый подписчик, мы возьмёмся за решение задач! Иначе говоря, будем заниматься тем, для чего и предназначено программирование! А ведь, к сожалению, очень часто изучение программирования подменяется изучением возможностей языка. Мы с вами, уважаемый подписчик, постараемся не забывать, что язык Паскаль ­– всего лишь средство. Главное – уметь решать задачи.

Начнём мы с простейших линейных подпрограмм с результатами числового типа. При этом, как и полагается, сначала составим алгоритм на АЯ, а затем, переведя его на Паскаль, реализуем в виде программы.  

ПОСТРОЕНИЕ ЛИНЕЙНЫХ ПОДПРОГРАММ

1. Решение задачи “Равновеликий квадрат”.

Задача L.1.2. “Равновеликий квадрат”. Построить алгоритм и подпрограмму вычисления стороны квадрата, имеющего ту же площадь, что и круг с заданной длиной окружности L.

Условие задачи напоминает нам известную неразрешимую проблему “квадратуры круга”. Разумеется, речь может идти только о приближённом равенстве площадей круга и квадрата. Посмотрим, как бы эту задачу решал математик.

Для непосредственного ответа на вопрос задачи необходимо знать площадь квадрата S. Тогда сторона квадрата A могла бы быть определена по формуле A=Sqrt(S). По условию задачи площадь квадрата должна совпадать с площадью круга, которую можно вычислить по известной формуле S=π*R2.

Это даёт нам для стороны квадрата A новую формулу A=Sqrt(π*R2)=R* Sqrt(π). Здесь неизвестный радиус круга R можно легко найти из известной формулы для длины окружности L=2*π*R, откуда получаем R=L/(2*π).

Теперь, подставляя выражение для радиуса R в формулу для стороны A, окончательно находим: A=Sqrt(π)*L/(2*π)=L/(2*Sqrt(π)).

Таким образом, математик ответил бы на требование поставленной задачи, записав следующий алгоритм её решения:

алг СторонаКвадрата ( L: вещ): вещ

нач

               СторонаКвадрата := L / ( 2 * Sqrt(Pi))

кон

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

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

Таким образом, при построении алгоритмов решения задач следует, по возможности, отказываться от выполнения каких бы то ни было предварительных преобразований, подстановок и выводов окончательных формул. Рекомендуется использовать при построении алгоритмов общеизвестные формулы. Благодаря этому, алгоритм будет легче понят и проверен лицом, желающим его использовать. Указанные качества алгоритма считаются значительно более важными, нежели сжатость алгоритма. Кстати, и для разработчика алгоритма при таком подходе задача тоже упрощается. Ведь ему теперь не нужно тратить лишнее время на выполнение преобразований и вывод формул, постоянно рискуя ошибиться.

Алгоритм и его перевод на Паскаль лучше записать так:

алг Квадрат ( L: вещ): вещ

   дано длина окружности L  0

   надо значение стороны равновеликого квадрата

нач R, S: вещ

   R := L / ( 2 * Pi );

   S := Pi * R* R;

   Квадрат := Sqrt ( S )

кон

Function Square ( L: Real ): Real;
   Var R,S: Real;
Begin
   R := L / (2 * Pi);
   S := Pi * R * R;
   Square := Sqrt(S)
End;

Как видим, алгоритм Квадрат содержит три команды и использует две промежуточные переменные R и S для обозначения радиуса и площади. В первых двух командах присваивания при вычислении R и S непосредственно используются общеизвестные формулы для длины окружности и площади круга. Последняя команда присваивания даёт окончательный результат. 

2. Решение задачи “Обмен значениями”.

Задача L.1.3. “Обмен  значениями”. Заданы переменные A  и  B. Построить алгоритм и подпрограмму обмена их значениями.

Смысл задачи объясним на примере. Предположим, что первоначально переменные A и B имеют значения 5 и 10 соответственно. Задача алгоритма состоит в том, чтобы переменные A и B приняли значения 10 и 5.

Совершенно очевидно, что пара команд присваивания A := B;  B := A к цели не приводит, так как сразу же после выполнения команды A := B переменная A станет равной B и, таким образом, первоначальное значение A будет утрачено. Следовательно, нечего будет передавать переменной B. 

Выход состоит в использовании промежуточной переменной C, которая используется для временного хранения значения переменной A. Для этого нужно выполнить команду C := A. Теперь уже можно переменной A передать значение переменной B с помощью команды A := B. Сама же переменная B получит значение переменной A от переменной C в результате выполнения команды B := C.

Из условия задачи следует, что переменные A и B являются одновременно и его аргументами, и его результатами. Поэтому обе эти переменные следует указать в заголовке алгоритма как результаты, а сам алгоритм оформить в виде процедуры.

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

алг Обмен ( рез A, B: <тип> )

   дано произвольные A и B совпадающего типа

   надо обменять значения A и B между собой

нач C: <тип>

   C := A; A := B; B := C

кон

Procedure Exchange ( Var A,B: T );
   Var C: T;
Begin
   C := A; A := B; B := C
End;

Работоспособность алгоритма не зависит от типа переменных A и B. Этот тип может быть любым из используемых в рамках АЯ, в том числе и структурированным. Важно только, чтобы типы переменных A и B, а также тип промежуточной переменной C, совпадали. 

Обратите внимание, что при переводе алгоритма на Паскаль использован нестандартный тип T. Поэтому, прежде чем описывать процедуру, в программе необходимо оформить раздел типов для описания типа T. Например, если вы собираетесь обменивать значения целочисленных переменных, то раздел типов может выглядеть так: Type T = Integer ; .

Решение данной задачи приведём также и в виде программы (см. предыдущее занятие).

{$B+,D+,E+,I+,L+,N+,Q+,R+,X-}

Program L_01_03;

   Type

      T=Integer;

   Procedure Exchange ( Var A,B: T );

      Var C: T;

   Begin

      C := A; A := B; B := C

   End;

   Var A,B: T;

Begin

   Write('Введите значения A и B: ');

   ReadLn(A,B);

   Exchange(A,B);

   WriteLn('A = ',A,', B= ',B);

End.

3. Решение задачи “Уравнение прямой”.

Задача L.1.7. “Уравнение прямой”. Прямая проходит через две несовпадающие точки (x1, y1) и (x2, y2). Построить алгоритм и подпрограмму определения коэффициентов уравнения прямой A * x + B * y + C = 0.

Тот, кто разбирается в математике, знает, что если переменные x и y связаны уравнением первой степени A * x + B * y + C = 0, в котором по крайней мере одно из чисел A, B не равно нулю, то графиком такой функциональной зависимости есть прямая линия. Поскольку через две несовпадающие точки на плоскости может проходить всего лишь одна прямая, то коэффициенты уравнения этой прямой должны непосредственно зависеть от координат этих точек.

Подставим координаты заданных точек (x1, y1) и (x2, y2) в уравнение прямой и получим систему двух уравнений с тремя неизвестными, из которой мы должны будем получить выражения для вычисления коэффициентов:

A * x1 + B * y1 + C = 0,

* x2 + B * y2 + C = 0.

Вычтем из второго уравнения первое и получим новую систему, равносильную данной:

* ( x2  x1 ) + B * ( y2  y1 ) = 0,

* x1 + B * y1 + C = 0.

Известно, что решая систему двух уравнений с тремя неизвестными, одно из них можно выбрать произвольно. Выберем A = y2 – y1, так как при этом путь решения получается наиболее простым и коротким. Действительно, из первого уравнения системы при этом легко определить B =  (x2 – x1). Из второго же уравнения системы, зная A и B, легко найти C = –A*x1 – B*y1. Именно эти соотношения и реализованы в алгоритме Прямая.

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

алг Прямая (арг x1,y1,x2,y2: вещ; рез A,B,C: вещ)

   дано координаты двух точек, x1¹x2 или y1¹y2

   надо коэффициенты уравнения A*x+B*y+C=0

нач

   A := y2 – y1;   B := x1 – x2;

   C := – x1 *  y1 * B

кон

Procedure Line(x1,y1,x2,y2:Real; Var A,B,C:Real);
Begin
   A := y2 - y1;
   B := x1 - x2;
   C := -x1 * A - y1 * B
End;

При использовании рассмотренного алгоритма важно понимать, какие значения исходных данных являются допустимыми для него. В условии задачи сказано, что прямая проходит через две несовпадающие точки. Это действительно важно, так как в противном случае получаем одновременно A=0 и B=0. А при таких значениях коэффициентов уравнение A * x + B * y + C = 0 не может быть уравнением прямой. Легко видеть, что заданные точки будут несовпадающим, если  x1 ¹ x2  или  y1 ¹ y2.

4. Решение задачи “Секунды ® Время”.

Задача L.3.1. “Секунды ® Время”. Начиная с некоторого момента времени прошло K полных секунд. Построить алгоритм,  выражающий пройденное время в полных часах, минутах и секундах.

Смысл задачи ясен из следующего примера. Предположим, что некоторый промежуток времени представлен как 2 часа 17 минут 35 секунд. Прежде всего обратим внимание, что указанное число минут меньше 60. Если бы это было не так, то для правильного указания промежутка времени следовало бы увеличить на 1 количество часов и соответственно уменьшить на 60 количество минут. Аналогичное замечание можно сделать и в отношении секунд. Таким образом, из условия задачи следуют естественные ограничения на количество минут 0  M < 60 и секунд 0  С < 60. На количество часов верхняя граница не устанавливается, поэтому Ч  0. Указанный промежуток времени можно измерить также и в полных секундах. Их количество составляет К = 2 * 3600 + 17 * 60 + 35 = 8255. Вполне очевидно, что К  0. Сформулировання задача требует осуществить обратный процесс, то есть по заданной длительности промежутка времени, выраженной количеством полных секунд К, определить соответствующие значения полных часов Ч, минут М и секунд С.

Порядок вычисления результатов может быть следующим.

Требуемое число секунд С может быть выделено сразу путём вычисления остатка от деления количества секунд К на 60, то есть С = К mod 60. Действительно, 8255 mod 60 = 35 секунд. Далее можно определить, какое полное количество минут содержит значение К. Для этого достаточно найти результат целочисленного деления К на 60. Действительно, К div 60 = 137 минут. В алгоритме полученное значение количества минут можно будет присвоить той же переменной К, поскольку предыдущее её значение больше не понадобится.  Следовательно, теперь К = 137 минут. Далее требуемое значение минут М может быть выделено путём вычисления остатка от деления количества минут К на 60, то есть М = К mod 60. Действительно, 137 mod 60 = 17 минут. И наконец, требуемое количество часов Ч может быть выделено из количества минут К путём целочисленного деления К на 60, то есть Ч = К div 60. Действительно, 137 div 60 = 2 часа.

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

алг Сек_Время ( арг К: нат; рез Ч, М, С: нат )

   дано количество секунд К  0

   надо количество полных часов Ч, минут М и секунд С

нач

   С := К mod 60;  К := К div 60;

   М := К mod 60;  Ч := К div 60

Кон

Procedure Second_Time(K:LongInt; Var
 
 Hour:LongInt; Var Minute,Second: Byte);
Begin
   Second := K Mod 60; K := K Div 60;
   Minute := K Mod 60; Hour := K Div 60
End;

Учитывая количество результатов, алгоритм Сек_Время представлен в виде процедуры. По условию задачи все значения фигурируют как полные. Это значит, что для них должен быть выбран целочисленный тип. При этом указанные выше ограничения значений переменных алгоритма позволяют остановиться на натуральном типе. При переводе на Паскаль в процедуре Second_Time конкретный целочисленный тип был выбран в зависимости от возможных предельных значений величин (тип LongInt – для часов, тип Byte – для минут и секунд).

Решение данной задачи приведём также и в виде программы (см. предыдущее занятие).

{$B+,D+,E+,I+,L+,N+,Q+,R+,X-}

Program L_03_01;

   Procedure Second_Time(K:LongInt; Var Hour:LongInt; Var Minute,Second: Byte);

   Begin

      Second := K Mod 60; K := K Div 60;

      Minute := K Mod 60; Hour := K Div 60

   End;

   Var K,H: LongInt; M,S: Byte;

Begin

   Write('Введите количество секунд K = ');

   ReadLn(K);

   Second_Time(K,H,M,S);

   WriteLn('Время: ',H,' час ',M,' мин ',S,' сек');

End.

Обратите внимание! Раздел переменных данной программы Var помещён рядом с исполняемой её частью. Так удобнее.

И ещё одно. Тексты приведённых программ можно переносить в окна текстового редактора ИСП непосредственно (см. занятие 11).

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

С другими алгоритмами такого же плана можна ознакомиться на моём персональном сайте по ссылке http://a-morgun.narod.ru/a06-01/a0006-0001-0005.html.

Более подробно ознакомиться со структурой программы на языке Паскаль можно там же по ссылке http://a-morgun.narod.ru/a08-01/a0008-0001-0001-0002.html.

Примечание. Буквенно-цифровая система обозначения задач (алгоритмов, подпрограмм, программ) дана в соответствии с книгой Моргун А.Н. Справочник по Turbo Pascal для студентов. – М.: Вильямс, 2006. – 608 с.   

Уважаемый подписчик! При необходимости задать вопрос, проконсультироваться, уточнить или обсудить что-либо обращайтесь через Гостевую книгу моего персонального сайта http://a-morgun.narod.ru

С уважением, Александр.


В избранное