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

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

  Все выпуски  

Занятие 35.


Сегодняшнее наше занятие, уважаемые подписчики, – последнее из посвящённых ветвлениям. Как и прежде, мы будем активно использовать модуль Problem.

Чем же мы будем заниматься потом? Конечно же, циклами! Кроме того, нам необходимо будет закрыть имеющиеся пробелы в изучении операторов ввода-вывода, а также поближе познакомиться со средствами ИСП для отладки программ.

И ЕЩЁ ПАРА ЗАДАЧ НА ВЕТВЛЕНИЯ

1. Решение задачи “Упорядочение”.

Задача V.3.1. “Упорядочение”. Заданы произвольные числа A и B. Построить подпрограмму упорядочения их по возрастанию.

Упорядочение двух чисел – простейшая из задач упорядочения. Но даже и в этом случае сначала придётся решить принципиальный вопрос, при каких условиях числа можно считать упорядоченными по возрастанию? Если числа разные, то ответ очевиден: последующее число должно быть больше предыдущего. Например, 5 и 7. Но как быть, если числа равны между собой? О каком возрастании может идти речь? Может быть, считать, что в этом случае задача не имеет решения?

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

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

Всё вышесказанное относится к упорядочению числовых констант. А как быть с переменными? Для упорядочения переменных в принципе существуют две возможности.

Во-первых, можно переставлять местами сами переменные. Например, если A=10 и B=5, то записав переменные в порядке BA, можно утверждать, что они упорядочены по возрастанию. Однако, такой способ упорядочения скрывает практически неразрешимую проблему: каким образом в качестве результата работы подпрограммы можно зафиксировать иной порядок следования переменных?

Во-вторых, можно переставлять местами значения переменных. Порядок следования самих переменных при этом остаётся неизменным. Например, если A=10 и B=5, то обменяв их значения и получив A=5 и B=10, можно утверждать, что нам удалось упорядочить их значения по возрастанию. Реализовать способ такого обмена можно достаточно просто.

Таким образом, у нас не остаётся выбора: упорядочивать переменные мы будем посредством  обмена их значений при фиксированном порядке следования.

Для обмена значений переменных A и B воспользуемся подпрограммой L.1.3 (процедура Exchange), изученной в материалах занятия 13. К этой подпрограмме обращение должно выполняться в том случае, если A > B, то есть значения переменных не упорядочены по возрастанию.

Поставленную задачу решает подпрограмма Regulate. В ней одни и те же переменные A и B выступают как в качестве исходных данных, так и в качестве результатов, то есть обе должны быть оформлены как Var-параметры. Это вполне естественно, так как в результате обмена значения обеих переменных могут быть изменены. По этой же причине подпрограмму целесообразно оформить в виде процедуры. Процедура Regulate может быть легко модифицирована для упорядочения по убыванию заменой знака “ > “ знаком “ < “.

Процедура Regulate имеет вид:

Procedure Regulate ( Var A, B: T );
Begin

  
If A > B Then Exchange ( A, B )
End;

В таком виде процедура может использоваться для упорядочения переменных любого типа. Необходимо только в программе предварительно оформить соответствующий раздел типов, например, Type T=Real. Кроме того, в программе необходимо разместить также и саму вспомогательную процедуру Exchange.

Если же необходимо упорядочивать переменные типа Integer, то для этого можно воспользоваться процедурой Exchange, размещённой в модуле Problem http://a-morgun.narod.ru/a08-01/a0008-0001-0002.html. В этом случае программа решения задачи будет иметь следующий вид:

{$B+,D+,E+,I+,L+,N+,Q+,R+,X-}
Program V_03_01;
   Uses Problem;
   Type T=Integer;

   Procedure Regulate ( Var A, B: T );
   Begin
      If A > B Then Exchange ( A, B )
   End;
   Var A,B: T;
Begin
   Write('Введите числа A и B: ');
   ReadLn(A,B);
   Regulate ( A, B );
   WriteLn( 'Числа упорядочены: A = ', A, ', B = ', B )
End.

2. Решение задачи “Пересечение прямых”.

Задача V.3.7. “Пересечение прямых”. Построить подпрограмму, которая определяет взаимное положение двух заданных прямых на плоскости, а также координаты точки пересечения, если они пересекаются. Известно, что каждая прямая проходит через две несовпадающие точки: первая – через точки (x1, y1) и (x2, y2), вторая – через точки (x3, y3) и (x4, y4).

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

Если прямые пересекаются, то координаты точки пересечения можно вычислить, решая совместно уравнения этих прямых. Однако, известно (см. материалы занятия 34), что при решениии системы двух линейных уравнений с двумя неизвестными возможно не только единственное решение. Решения могут отсутствовать, их также может быть бесчисленное множество. В приложении к прямым на плоскости отсутствие решений системы означает, что прямые параллельны, а в случае бесчисленного множества решений системы имеем соответственно совпадение прямых.

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

В свою очередь, коэффициенты уравнения каждой прямой A*x + B*y + C = 0 можно получить с помощью процедуры L.1.7 Line, исходя из значений координат двух несовпадающих точек, через которые она проходит (см. материалы занятия 13). Обратившись к ней дважды, получим значения коэффициентов уравнений обоих прямых, обозначив их A1B1C1 и A2B2C2 соответственно. В свою очередь, эти коэффициенты используются при обращении к процедуре System_Equation. При этом у коэффициентов C1 и C2 знак следует изменить на обратный, так как они соответствуют свободным членам системы уравнений, в которой каждое уравнение имеет вид A*x + B*y = C.

Решение рассмотренной задачи оформлено в виде процедуры CrossLine.

Procedure CrossLine(x1,y1,x2,y2,x3,y3,x4,y4:Real; Var x,y:Real; Var z:Byte);
   Var A1,B1,C1,A2,B2,C2: Real;
Begin
   Line(x1,y1,x2,y2,A1,B1,C1);
   Line(x3,y3,x4,y4,A2,B2,C2);
   System_Equation(A1,B1,-C1,A2,B2,-C2,x,y,z);
End;

Исходными данными процедуры CrossLine являются координаты несовпадающих точек (x1, y1) и (x2, y2), через которые проходит первая прямая, и несовпадающих точек (x3, y3) и (x4, y4), через которые проходит вторая прямая. Результатами процедуры являются координаты возможной точки пересечения (x, y), а также флажок z, значения которого совпадают со значениями флажка, получаемого при решении системы. При этом смысл значений флажка изменяется так, как оговаривалось выше.

Если используются процедуры Line и System_Equation, размещённые в модуле Problem http://a-morgun.narod.ru/a08-01/a0008-0001-0002.html, то программа решения задачи будет иметь следующий вид:

{$B+,D+,E+,I+,L+,N+,Q+,R+,X-}
Program V_03_07;
   Uses Problem;

   Procedure CrossLine(x1,y1,x2,y2,x3,y3,x4,y4:Real; Var x,y:Real; Var z:Byte);
      Var A1,B1,C1,A2,B2,C2: Real;
   Begin
      Line(x1,y1,x2,y2,A1,B1,C1);
      Line(x3,y3,x4,y4,A2,B2,C2);
      System_Equation(A1,B1,-C1,A2,B2,-C2,x,y,z);
   End;
   Var x1,y1,x2,y2,x3,y3,x4,y4,x,y: Real;
       z: Byte;
Begin
   Write('
Введите координаты точек
x1,y1,x2,y2: ');
   ReadLn(x1,y1,x2,y2);
   Write('
Введите координаты точек x3,y3,x4,y4: ');
   ReadLn(x3,y3,x4,y4);
   CrossLine(x1,y1,x2,y2,x3,y3,x4,y4,x,y,z);
   Case z Of
      1: WriteLn('
Прямые пересекаются в точке (',x:0:4,', ',y:0:4,')');
      2: WriteLn('
Прямые совпадают
');
      3: WriteLn('
Прямые параллельны
');
   End
End.

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

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


В избранное