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

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

  Все выпуски  

Занятие 26.


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

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

ЕЩЁ ПАРА ЗАДАЧ НА МНОЖЕСТВЕННЫЕ ВЕТВЛЕНИЯ

1. Решение задачи “Сравнение”.

Задача V.2.3. “Сравнение”. Иванову X лет, Петрову Y лет. Построить алгоритм и подпрограмму сравнения возрастов Иванова и Петрова.

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

Выбор большей из двух величин нами уже обсуждался в материалах занятия 23  (алгоритм V.1.3 “Большее из двух”). При этом мы договорились, что большая из двух величин это всегда одна из этих величин. Иными словами говоря, значение результата получается одним из двух возможных.

Сравнение величин принципиально отличается тем, что имеет место один из трёх вариантов:

-       первая величина больше второй;

-       вторая величина больше первой;

-       величины равны между собой.

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

Теперь обсудим, каким образом можно представить результат этого алгоритма.

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

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

Именно поэтому рекомендуется результат сравнения двух величин представить в виде значения некоторого флажка числового типа. Логический тип тут не подойдёт, так как возможны три разных значения этого флажка. Числовой вещественный тип для этой цели также не подходит, поскольку значения флажка должны представляться точно. Тип флажка может быть выбран либо целым, либо натуральным.

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

алг Вариант ( X, Y: вещ ): нат
нач
   выбор
      при X > Y: Вариант := 1  { Иванов старше Петрова }
      при
Y > X: Вариант := 2  { Петров старше Иванова }
      иначе Вариант := 3
          { возрасты обоих равны }
   кв
кон

Function Comparison ( X,Y: Real ): Byte;
Begin
   If X > Y Then Comparison := 1
      Else If Y > X Then Comparison := 2
         Else Comparison := 3
End;

Алгоритм построен в виде функции Вариант натурального типа с вещественными аргументами, значения которых ограничены естественным образом (> 0, > 0). Значениями функции являются значения флажка, образованные обычной порядковой нумерацией вариантов сравнения величин. По существу, такая нумерация представляет собой кодирование возможных значений результата сравнения. И в алгоритме на АЯ, и в подпрограмме на Паскале значения кодов можно расшифровать с помощью комментариев, указанных в фигурных скобках.

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

2. Решение задачи “Вычисление сложной комбинированной функции с разрывами”.

Задача V.2.2. “Вычисление сложной комбинированной функции с разрывами”. Для заданного произвольного значения аргумента построить алгоритм и подпрограмму вычисления значения комбинированной функции

Проанализируем свойства сформулированной задачи:

-       области действия отдельных составляющих заданной комбинированной функции не пересекаются;

-       любая из составляющих заданной комбинированной функции может быть вычислена (определена) во всех точках своей области действия;

-       области действия составляющих заданной комбинированной функции  имеют разрыв!

Последнее обстоятельство вынуждает нас сделать два очень важных вывода.

Вывод 1. Вычисление функции возможно не при любом значении аргумента, а именно, условием задачи при –1 <= x <= 1 оно не предусмотрено вообще. Следовательно, при построении данного алгоритма следует организовать получение двух результатов (значений функции y и флажка z) так же, как это было сделано в алгоритме V.1.2 (см. материалы занятия 23). Логическое значение флажка должно будет указывать нам, удалось (= ДА) или не удалось (= НЕТ) вычислить значение функции при данном значении аргумента. Естественно, алгоритм должен быть построен в виде процедуры.

Вывод 2. То, что при –1 <= x <= 1 вычисление значения функции не предусмотрено, говорит о фактическом наличии в данной задаче третьей скрытой ветви. По первым двум, указанным в условии задачи, значение функции вычисляется, а по третьей, скрытой, не вычисляется. Это, в свою очередь, значит, что алгоритм должен быть построен с использованием команды выбора.  

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

-       при < –1 функция вычисляется по первой формуле, значение флажка истинно; значения < –1 исключаются из дальнейшего рассмотрения, что значит автоматическое выполнение условия >= –1;

-       при <= 1 функция не вычисляется, значение флажка ложно; значения <= 1 исключаются из дальнейшего рассмотрения, что значит автоматическое выполнение условия > 1;

-       при > 1 функция вычисляется по второй формуле, значение флажка истинно; поскольку условие > 1 выполняется автоматически, то всё это может быть указано в альтернативной ветви команды выбора.     

Таким образом, получаем запись алгоритма ЗначКФР (Значение Комбинированной Функции с Разрывами), которую можно назвать канонической:

алг ЗначКФР ( арг x: вещрез y: вещz: лог )
нач
   выбор
      при < –1: нс := Ln (2  x) / Ln (10); := ДА кс
      при 
<= 1: := НЕТ
      иначе нс y := Sqrt (+ 1); := ДА кс
   кв
кон

К сожалению, с эстетической точки зрения в таком виде алгоритм не выдерживает критики. Во-первых, из-за наличия в ветвях по две команды возникает необходимость использования служебных слов нс и кс. А во-вторых, неприятно бросается в глаза повторное использование команды := ДА. Всё это отнюдь не украшает алгоритм, делает его громоздким. Именно поэтому полученная каноническая запись подлежит оптимизации.

Для оптимизации алгоритма используем алгоритмический приём, имеющий название “формулирование предположения с последующей его проверкой и уточнением”. Предположим, что при данном значении аргумента функцию вычислить возможно. Такое предположение эквивалентно тому, что команда := ДА записывается один раз перед командой выбора. При этом все ветви команды выбора, в которых теперь осталось по одной команде, помимо вычисления значения функции, фактически заняты проверкой того, не следует ли изменить значение флажка z на противоположное.

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

алг ЗначКФР ( арг x: вещрез y: вещz: лог )
нач
   
:= ДА
   выбор
      при 
< –1: := Ln (2  x) / Ln (10)
      при <= 1: z := НЕТ  
      иначе := Sqrt (+ 1)
   кв
кон

Procedure Signify_Complex(x:Real; Var y:Real; Var z:Boolean );
Begin

  
z := True;
  
If x < -1 Then y := Ln(2-x)/Ln
(10)
     
Else If x <= 1 Then z := False

         Else y := Sqrt(x+1)
End;

Решение данной задачи приведём также и в виде программы:

{$B+,D+,E+,I+,L+,N+,Q+,R+,X-}
Program V
_02_02;
  
Procedure Signify_Complex ( x: Real; Var y: Real; Var z: Boolean
);
  
Begin

     
z := True;
     
If x < -1 Then y := Ln(2-x)/Ln
(10)
        
Else If x <= 1 Then z := False

            Else y := Sqrt(x
+1)
  
End
;
  
Var x,y: Real; z: Boolean
;
Begin

  
Write('Введите значение аргумента x: ');
  
ReadLn(x
);
  
Signify_Complex (x, y, z
);
  
If z Then WriteLn('Значение функции y=', y
:0:4)
       
Else WriteLn
('Значение функции вычислить невозможно')
End.

Уважаемые подписчики! На следующем занятии мы с вами рассмотрим специфические средства реализации множественных ветвлений, предусмотренные в языке Паскаль.

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

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

 


В избранное