Вложенные циклы
Если телом цикла является циклическая структура, то такие циклы называют вложенными или сложными. Цикл, содержащий в себе другой цикл, называют внешним. Цикл, содержащийся в теле другого цикла, называют внутренним.
Внутренний и внешний циклы могут быть любыми из трех рассмотренных видов: циклами с параметром, циклами с предусловием, циклами с постусловием. При построении вложенных циклов необходимо соблюдать следующее дополнительное условие: все операторы внутреннего цикла должны полностью лежать в теле внешнего цикла, циклы ни в коем случае не могут пересекаться.
Сложные циклы условно разбивают на уровни вложенности. Ниже представлена структура вложенных циклов с параметром, для которой: внешний цикл 1 имеет уровень 0, внутренний цикл 2 – уровень 1, внутренний цикл 3 – уровень 2.
Возможная глубина вложенности циклов (количество уровней) ограничивается объемом имеющейся памяти ЭВМ. Заметим, что цикл 2 является внешним по отношению к циклу 3 и внутренним по отношению к циклу 1. Параметры циклов разных уровней изменяются не одновременно. Вначале все свои значения изменит параметр самого внутреннего цикла при фиксированных значениях параметров циклов с меньшим уровнем - это цикл 3. Затем меняется на один шаг значение параметра следующего уровня (цикла 2) и снова полностью выполняется внутренний цикл и т. д. до тех пор, пока параметры циклов всех уровней не примут все требуемые значения. При этом, если в сложном цикле с глубиной вложенности k число повторений циклов на каждом уровне равно N0, N1, …, Nk соответственно, то общее количество повторений тела самого внутреннего цикла равно:
N= N0 × N1 × …× Nk .
Рисунок 3 – Схема алгоритма с вложенными циклами
На рис. 3 изображен цикл с параметром. Но все изложенное относится и к тем случаям, когда для организации циклов используются другие виды циклических структур: цикл с предусловием или цикл с постусловием.
Рассмотрим конкретную задачу, требующую для своего решения организации вложенных циклов. Такой задачей является задача табулирования функции нескольких переменных.
Пример 3. Построить алгоритм и написать программу вычисления значений функции z=cos x + y, где x = xn (hx) xk и y = yn (hy) yk . Аргументы функции x, y – действительные числа.
Для определения значений функции z для всех различных пар (x, y) необходимо процесс вычислений организовать следующим образом. Вначале при фиксированном значении одного из аргументов, например при x=x0, вычислить значения z для всех заданных y: yn , yn + hy , …, yn . Затем, изменив значение х на x + hx , вновь перейти к полному циклу изменения переменной y. Данные действияповторить для всех заданных x: xn , xn + hx , …, xn. При реализации данного алгоритма требуется структура вложенных циклов: внешнего цикла – для изменения значений переменной х и внутреннего цикла – для изменения значений переменной у. Причем в данной задаче внешний и внутренний циклы можно поменять местами, при этом изменится только очередность изменения аргументов при вычислении функции. В качестве внешнего и внутреннего циклов можно использовать циклы с параметром, циклы с предусловием или с постусловием.
Рисунок 4 – Схема алгоритма к примеру 3
Алгоритм решения поставленной задачи, выполненный с применением цикла с параметром, представлен на рис. 4. Программа, соответствующая этому алгоритму, представлена в листинге 3.
Листинг 3
using System;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
double xn, xk, hx, yn, yk, hy, z;
Console.Write("Enter xn ");
xn = Convert.ToDouble(Console.ReadLine());
Console.Write("Enter xk ");
xk = Convert.ToDouble(Console.ReadLine());
Console.Write("Enter hx ");
hx = Convert.ToDouble(Console.ReadLine());
Console.Write("Enter yn ");
yn = Convert.ToDouble(Console.ReadLine());
Console.Write("Enter yk ");
yk = Convert.ToDouble(Console.ReadLine());
Console.Write("Enter hy ");
hy = Convert.ToDouble(Console.ReadLine());
for (double x = xn; x <= xk; x += hx) // Внешний цикл
{
for (double y = yn; y <= yk; y += hy) // Внутрений цикл
{
z = Math.Cos(x) + y;
Console.WriteLine("х=" + x + " у=" + y + " z=" + z);
}
}
}
}
}
Пример 4. Вычислить с погрешностью e значения функции y = cos(x), используя разложение cos x в ряд, для значений x = xn (hx) xk .
Вычислить значение функции cos x можно путем разложения его в следующий ряд:
Cos x = 1 - + - + …+(-1)n +...
Рисунок 5 – Схема алгоритма к примеру 4
Задача вычисления y = cos x для фиксированного значения х была рассмотрена в примере 1. В данном случае сумму ряда S необходимо вычислять для каждого значения х из диапазона [xn , xk]. Следовательно, необходимо использовать структуру вложенных циклов. Как показано на схеме алгоритма (рис. 5), внешний цикл – цикл для изменения значений переменной х (цикл с предусловием). Внутренний цикл – цикл для вычисления суммы ряда при фиксированном значении х с погрешностью вычислений e (также цикл с предусловием).
Все вышесказанное реализовано в программе, соответствующей схеме данного алгоритма.
В данном случае сумму ряда S необходимо вычислять для каждого значения х из диапазона [xn, xk]. Следовательно, необходимо использовать структуру вложенных циклов. Как показано на схеме алгоритма, внешний цикл – цикл для изменения значений переменной х (цикл с предусловием). Внутренний цикл – цикл для вычисления суммы ряда при фиксированном значении х с погрешностью вычислений e (также цикл с предусловием).
Правильность работы программы оценивается путем сравнения значения s с его вычисляемым по формуле y=cos(x) значением.
Соответствующая программа представлена в листинге 4.
Листинг 4
using System;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
double xn, xk, hx, eps,s,t,y,f;
Console.Write("Enter xn ");
xn = Convert.ToDouble(Console.ReadLine());
Console.Write("Enter xk ");
xk = Convert.ToDouble(Console.ReadLine());
Console.Write("Enter hx ");
hx = Convert.ToDouble(Console.ReadLine());
Console.Write("Enter eps ");
eps = Convert.ToDouble(Console.ReadLine());
double x= xn;
while (x<=xk)
{ //Внешний цикл
s=0;
t=1;
int n=1;
while (Math.Abs(t) > eps)
{ //Внутренний цикл
s= s + t;
f= -x*x / (2*n*(2*n-1));
t= t*f;
n++;
} //Конец внутреннего цикла
y= Math.Cos (x);
Console.WriteLine("х=" + x + " у=" + y+ " s="+s);
x= x + hx;
} //Конец внешнего цикла
}
}
}
Выше были рассмотрены основные управляющие конструкции языка Паскаль, позволяющие осуществлять программную реализацию различных ветвлений и циклов. Любой алгоритм (программа) представляет собой некоторую комбинацию рассмотренных стандартных структур: линейной, разветвляющейся, циклической.
Пример 5. Составить программу нахождения наибольшего общего делителя (НОД) двух целых чисел M и N.
Рисунок 6 – Схема алгоритма к примеру 5
Программа представлена в листинге 5.
Листинг 5
using System;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
int m,n,nod;
Console.Write("Enter m ");
m = Convert.ToInt32(Console.ReadLine());
Console.Write("Enter n ");
n = Convert.ToInt32(Console.ReadLine());
while (m!=n)
{
if (m > n) m= m - n;
else n= n-m;
}
nod= m;
Console.WriteLine("nod=" + nod);
}
}
}
Программа представляет собой сочетание линейной, циклической и разветвляющейся структур. Телом цикла с предусловием является разветвление.