Сегодня мы с вами, уважаемые подписчики, уделим внимание построению алгоритмов и подпрограмм с командой ветвления.
Методы использования команды ветвления в АЯ и в Паскале практически совпадают.
ПОСТРОЕНИЕ АЛГОРИТМОВ С КОМАНДОЙ ВЕТВЛЕНИЯ
1. Решение задачи “Вычисление функции с разрывами”.
Задача V.1.2. “Вычисление функции с разрывами”. Для заданного произвольного значения
аргумента построить алгоритм и подпрограмму вычисления значения функции
.
Рассмотрим подход к построению алгоритмов вычисления функций в тех случаях, когда значения аргумента по условию задачи произвольны, но значения функции могут быть получены не при любом из них.
Будем считать, что некоторую сложную функцию в данной точке вычислить невозможно, если невозможно вычислить хотя бы одну из элементарных функций, входящих в её состав. В отношении такой сложной функции математики говорят, что данная точка не принадлежат области её определения и называют её функцией с разрывами.
Из сказанного следует очень простой вывод. Сложная функция может быть вычислена, если данное значение аргумента принадлежит области определения всех элементарных функций, входящих в её состав.
В математике рассматриваются многие элементарные функции, в область определения которых входят не все действительные числа. Перечислим их:
1). Дробную функцию X / Y можно вычислить всюду, где соблюдается условие Y <> 0. В противном случае имеем деление на нуль.
2). Вычисление показательно-степенной функции XY достаточно рассмотреть только при Y >= 0. При Y < 0 взамен следует рассматривать функцию 1 / X–Y, то есть сначала пытаться возводить в положительную степень, а потом выполнять деление. При Y >= 0
вычисление XY невозможно в следующих случаях:
а) если X = 0, то функцию XY невозможно вычислить при Y = 0, так как имеет место неопределённость вида 00;
б) если X < 0, то функция XY не может быть вычислена, если показатель степени Y нельзя представить в виде рационального числа p / q, где p и q – целые положительные взаимно простые числа;
в) если X < 0, а показатель степени Y имеет вид рационального числа p / q, где p и q – целые положительные взаимно простые числа, то функция XY не может быть вычислена в тех случаях, когда p – нечётно, а q – чётно.
Например, при X < 0 невозможно вычислить квадратный корень sqrt(X), так как при этом p = 1 –
нечётно, а q = 2 – чётно.
3). Логарифмическая функция ln(X) не может быть вычислена при X < 0.
Если требуется составить алгоритм вычисления функции с разрывами при произвольном значении аргумента, то необходимо учитывать ситуации, когда она не может быть вычислена. Это можно сделать единственным способом – предусмотреть в алгоритме не один, а два результата. Значение
функции – первый результат, который мы, естественно, получаем не во всех случаях. Второй результат – “флажок”. Флажок должен сигнализировать о том, удалось или не удалось получить первый результат. Существенно, что получение значения флажка в алгоритме должно быть обеспечено во всех случаях.
Выберем в качестве флажка логическую переменную z. Договоримся, что значение ДА этой переменной будет признаком возможности вычисления заданной функции при заданном значении аргумента. В противном случае значение флажка должно быть равно НЕТ. Таким образом, для вычисления флажка z следует записать такое логическое выражение,
которое было бы истинным только в случае принадлежности аргумента x области определения заданной функции. В противоположном случае это логическое выражение должно быть ложным.
Заданная функция содержит две элементарные составляющие: дробную и логарифмическую функции. Как уже указывалось выше, дробную функцию можно вычислить, если её знаменатель отличен от нуля, а логарифмическую, если её аргумент положителен. Вычисление заданной функции в целом возможно, если можно вычислить каждую из её составляющих. Очевидно, что истинным при сформулированных условиях будет логическое выражение
( Sin(x) <> 0 ) и ( Cos(x)>0 ). Следовательно, его можно использовать для вычисления значения флажка z.
Следующий шаг алгоритма – вычисление значения заданной функции. Используя команду ветвления в сокращённой форме, мы добиваемся того, чтобы это вычисление выполнялось только тогда, когда это возможно, то есть в случае истинности значения флажка z.
Алгоритм и его перевод на Паскаль выглядят следующим образом:
алг ЗначФР ( арг x: вещ; резy: вещ, z: лог
) дано произвольное значение аргумента x надозначение флажка z и функции y нач z := ( Sin(x)<>0 ) и ( Cos(x)>0; еслиzтоy := 1 / Sin(x) + Ln( Cos(x) ) / Ln(10) кон
Procedure Signify_Simple(x: Real; Var y: Real; Var z: Boolean); Begin z := ( Sin(x)<>0 ) And ( Cos(x)>0; If z Then y := 1 / Sin(x) + Ln( Cos(x) ) / Ln(10) End;
Обратите внимание, что алгоритм ЗначФР (Значение Функции с Разрывами) построен в виде процедуры, поскольку имеет два результата.
Решение данной задачи приведём также и в виде программы:
{$B+,D+,E+,I+,L+,N+,Q+,R+,X-} ProgramV_01_02; ProcedureSignify_Simple ( x: Real; Vary: Real; Varz: Boolean ); Begin z :=
(Sin(x)<>0) And (Cos(x)>0); IfzTheny := 1/Sin(x) + Ln(Cos(x))/Ln(10) End; Varx,y: Real; z: Boolean; Begin Write('Введите
значение аргумента x: '); ReadLn(x); Signify_Simple (x, y, z); IfzThenWriteLn('Значение функции y=', y:0:4) ElseWriteLn('Значение функции вычислить невозможно') End.
2. Решение задачи “Большее из двух”.
Задача V.1.3. “Большее из двух”. Заданы произвольные числа A и B. Построить алгоритм и подпрограмму выбора большего из них.
Сначала обсудим смысл понятия “большее из двух”. Нет никаких сомнений, что в случае выбора большего из двух неравных чисел ответ будет однозначным всегда. Например, 20 – большее из двух чисел 20 и 10, 30 – большее из двух чисел 10 и 30 и т. п.
Но каким будет ответ, если числа равны? И каким он должен быть? Человек, не искушённый в алгоритмизации, пожалуй, откажется выбрать какое-либо из них. Он ответит, что среди двух равных чисел большее выбрать невозможно. Но, ведь для нас с вами это значило бы невозможность получить значение результата алгоритма. Иначе говоря, бытовые представления о том, что среди двух равных чисел выбрать большее невозможно,
здесь неприменимы, поскольку это резко ухудшило бы свойство массовости соответствующего алгоритма.
Поэтому подойдём к ответу на этот вопрос с иных позиций. Предположим, что вы заблудились на совершенно ровном поле и хотите стать в самой высокой его точке, чтобы осмотреться вокруг и выбрать направление движения. Неужели вы откажетесь от мысли осмотреться вокруг и от выбора направления движения на том основании, что на совершенно ровном поле самая высокая точка отсутствует? Скорее всего, вы остановитесь
в любой точке. И будете правы. А нам с вами именно такой подход даёт возможность получить значение результата алгоритма в любом случае.
Наша задача выбора большего из двух чисел уже почти решена. Конечно же, мы будем строить алгоритм, который даёт результат при любых исходных данных. К сожалению, невозможно построить алгоритм, который в случае равенства двух чисел в качестве большего выбирал бы любое. Действия алгоритма не могут быть подвержены случайности, они должны быть чётко определены. Поэтому чисто формально договоримся в случае равных чисел большим считать второе из них.
Формальные договорённости подобного рода достаточно часты в практике алгоритмизации. Их главный смысл состоит в том, чтобы избежать ситуации “буриданова осла”, который умер от голода, будучи не в состоянии выбрать лучшую из двух совершенно одинаковых охапок сена. Такая договорённость как раз и обеспечивает
нам получение результата решения задачи при максимальном числе вариантов исходных данных.
Разумеется, при выборе большего из двух чисел нет необходимости в отдельной проверке на равенство. Достаточно будет сказать, что если первое число больше второго, то значением результата должно быть значение первого числа. Во всех остальных случаях (в том числе и в случае равенства) значением результата должно быть значение второго числа.
При таком подходе для построения алгоритма БИД (Большее Из Двух) достаточно проверить всего одно условие A > B, и поэтому может быть использована всего одна команда ветвления в полной форме, а именно: если A > B то БИД := A иначе БИД := B.
Обратите внимание, что алгоритм БИД целесообразно построить в виде функции. И не удивительно. Ведь наш алгоритм в состоянии выдать единственное значение результата при любых исходных данных. И никакие флажки, сигнализирующие о возможности получения результата, нам здесь не нужны.
Алгоритм и его перевод на Паскаль выглядят следующим образом:
алг БИД ( A, B: <числовой тип> ): <числовой тип> дано значения переменных Aи Bчислового типа надозначение большей из них нач еслиA > Bто БИД := A иначе БИД := B кон
Function Greater ( A, B: T ): T; Begin If A > B Then Greater := A Else Greater := B End;
Очевидно, что как для исходных данных, так и для значения функции здесь возможен любой совпадающий числовой тип, что и отмечено условной записью <числовой тип>. В подпрограмме на Паскале это подчёркнуто применением нестандартного типа T. Поэтому, прежде чем использовать функцию Greater, в программе необходимо оформить соответствующий раздел типов, например, Type T
= Real.
Итак, уважаемые подписчики, только что мы рассмотрели алгоритм БИД, который по праву считается самым популярным из всех алгоритмов всех учебников информатики. Но, как это ни удивительно, и нам с вами удалось узнать о нём кое-что новенькое.
Решение и этой задачи также приведём в виде программы:
{$B+,D+,E+,I+,L+,N+,Q+,R+,X-} Program V_01_03; Type T=Real; Function Greater ( A, B: T): T; Begin If A
> B Then Greater := A Else Greater := B End; Var A,B: T; Begin Write('Введите числа A и B: '); ReadLn(A,B); WriteLn('Большее из двух равно ',Greater(A,B):0:4) End.
Уважаемые подписчики! Следующее занятие также будет посвящено построению алгоритмов и подпрограмм, использующих двойное ветвление.
Уважаемые подписчики!При необходимости задать вопрос, проконсультироваться, уточнить или обсудить что-либо обращайтесь через Гостевую книгу моего персонального сайта http://a-morgun.narod.ru. При этом настоятельно рекомендую пользоваться браузером Internet Explorer.