Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Информатика.doc
Скачиваний:
89
Добавлен:
15.03.2015
Размер:
2.58 Mб
Скачать

Тема 3: Циклические вычислительные процессы

Теоретический материал

Виды циклов

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

а) б)

Рис.3.1. Виды циклов: с предусловием – а) с постусловием – б)

В С++ для этих целей используются три взаимозаменяемых оператора цикла - while, do while и for. Во всех трех операторах должны присутствовать начальные установки, тело цикла, включающего операторы, которые и должны выполниться несколько раз, модификация параметра цикла и проверка условия продолжения цикла.

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

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

Цикл завершается, если условие его продолжения не выполняется.

Цикл с предусловием while

while (условное выражение)

оператор;

Проверка условия проводится перед выполнением цикла.

Возможна ситуация, когда тело цикла не выполнится ни разу. Это случится, если первая же проверка условия окажется ложной. Если же вычисленное условное выражение принимает значение true (отличается от нуля), то выполняется тело цикла (оператор) и повторяется вычисление условного выражения. Цикл продолжается до тех пор, пока условное выражение не станет false (равным нулю), после чего происходит выход из цикла. Как правило, в теле цикла должны изменяться значения одной или нескольких переменных, входящих в условное выражение c тем, чтобы в конце концов условное выражение стало ложным (обратилось в нуль), и цикл завершился. Для того чтобы условное выражение имело какое-то значение, перед входом в цикл в первый раз обычно надо инициализировать одну или несколько переменных, входящих в условное выражение.

Замечание.

Будьте осторожны при работе с циклами. Cуществует опасность попасть в бесконечный цикл.

Пример бесконечного цикла

#include<stdio.h>

int main() {

int n=2;

while(n>0)

printf(“работаем с циклом while”);

return 0;

}

Так как n всегда больше нуля, мы попадаем в бесконечный цикл.

Выход из цикла происходит в следующих случаях:

  • Условное выражение в заголовке цикла стало ложным (равным 0).

  • В теле цикла встретился оператор break.

  • В теле цикла выполнился оператор return.

В первых двух случаях управление передается на оператор, cтоящий сразу за оператором цикла. В третьем случае происходит возврат из функции.

Пример

Написать программу, которая печатает таблицу значений функции y=, для аргументов, изменяющихся в заданных пределах на интервале от 1.0 до 2.0 с шагом 0.1.

#include<stdio.h>

#include<math.h>

int main() {

float xn,xk,dx,x,y;

printf(“enter xn,xk,dx:\n”);

scanf(“%f %f %f\n”,&xn,&xk,&dx);

x=xn;

while(x<xk){

y=sqrt(x);

printf("\nx=%f y=%f\n",x,y);

x+=dx;

}

return 0;

}

Протокол работы

x=1.000000 y=1.000000

x=1.100000 y=1.048890

x=1.200000 y=0.094980

x=1.300000 y=1.140175

x=1.400000 y=1.183216

x=1.500000 y=1.224745

x=1.600000 y=1.264911

x=1.700000 y=1.303841

x=1.800000 y=1.341641

x=1.900000 y=1.378405

Прототип функции вычисления квадратного корня находится в заголовочном файле math.h, поэтому кроме подключения заголовочного файла stdio.h, необходимого для работы с функцией printf(), подключаем еще и заголовочный файл math.h.

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

Компилятор, прочтя первую строку тела функции выделит память для размещения данных xn, xk, dx, и память для текущих значений x и y. Следующая строка является интерфейсной подсказкой для пользователя, говорящая о том, что и в какой последовательности должно быть введено в память, выделенную для исходных данных.

Следующая строка позволяет пользователю ввести с клавиатуры по адресам, выделенным компилятором для исходных данных конкретные значения этих данных в формате f.

Для решения задачи будем использовать, например, цикл while.

Почему вообще здесь необходим цикл? Для любого очередного значения аргумента значение функции будет вычисляться по одной и той же формуле и сразу же выводиться на печать. Для каждого следующего аргумента надо изменить его значение на шаг dx и снова повторить однотипные действия вычисления функции и печати ее значения.

Обратите внимание, что до входа в цикл надо задать текущему значению x начальное значение, то есть x=xn.

При входе в цикл сразу же осуществляется проверка (x<xk). Если очередное текущее значение x <xk , то тело цикла будет выполнено от начала до конца, то есть будет вычислено значение функции при этом значении x , значения x и y будут выведены на печать, после чего прежде чем возвратиться в начало цикла, будет изменено текущее значение x на шаг dx. Только после этого мы вернемся в начало цикла, чтобы проверить выполняется ли условие(x<xk) для нового значения текущего x. Если выполняется, то тело цикла будет выполнено снова, но уже для другого значения x. И так будет повторяться до тех пор, пока x не достигнет значения, равного xk. В этот момент цикл закончит свою работу, и программа выйдет из цикла и перейдет к оператору, следующему за циклом. У нас после выхода из цикла больше операторов нет, следовательно, программа закончит свою работу.

Обратите внимание, что тело цикла заключено в фигурные скобки. По синтаксису языка и в теле цикла while, и в теле цикла do while разрешен только один оператор (простой). Если же вам необходимо использовать в теле цикла более одного оператора, то это уже будет составной оператор – блок, который необходимо взять в фигурные скобки.

Цикл с постусловием do while

Проверка условия осуществляется после выполнения тела цикла.

do

оператор

while (условное _выражение);

Цикл заканчивается, когда условное выражение становится ложным (обращается в нуль). Условия выхода из цикла такие же, как и для оператора while

Хотя бы один раз тело цикла выполнится до проверки условного выражения в отличии от цикла while в котором тело цикла может вообще не выполниться ни разу, если первая же проверка условия окажется ложной.

Пример. Решим ту же самую задачу, которую решали с циклом while , используя цикл с постусловием do while.

#include<stdio.h>

#include<math.h>

int main() {

float xn=1.0,xk=2.0,dx=0.1,x,y;

x=xn;

do{

y=sqrt(x);

printf("\nx=%f y=%f\n",x,y);

x+=dx;

}

while(x<xk);

return 0;

}

Результаты работы будут точно такими же, как и при решении задачи с помощью цикла while.

Рассмотрим еще один пример

Число x уменьшать в 2 раза до тех пор, пока оно не станет меньше 0.1

#include <stdio.h>

int main() {

float x=10;

do {

x=x/2;

printf(“x=%f”,x);

}

while(x>=0.1);

return 0 ;

}

Самостоятельно проанализируйте эту маленькую программу.

Цикл for

for([выражение1];[выражение2];[выражение3])

оператор

Каждое из 3 выражений можно опустить. Обычно первое выражение служит для инициализации индекса, второе –для проверки продолжения цикла, третье -для изменения значения индекса.(хотя программист имеет право использовать эти выражения как ему угодно).

Формально алгоритм работы выглядит так:

1 Если первое выражение присутствует, то оно вычисляется.

2 Если присутствует второе выражение, то и оно вычисляется. Если при вычислении получается значение false (0),то цикл прекращается, иначе- будет продолжен.

3 Исполняется тело цикла.

4 Если присутствует третье выражение, то оно вычисляется

5 Переходим к пункту 2.

Появление в любом месте тела цикла оператора continue приведет к немедленному переходу к шагу 4. Оператор continue пропускает все операторы, оставшиеся до конца цикла и передает управление на начало следующей итерации.

Пример

Напечатать четные числа от 10 до 0

Вариант 1:

#include<stdio.h>

int main() {

int i;

for(i=10; i>=0; i - =2)

printf(“%d ”, i);

return 0;

}

Протокол работы:

10 8 6 4 2 0

или вариант 2:

#include<stdio.h>

int main() {

int i;

for(i=10; i>=0; printf(“%d ”,i), i - =2);

return 0;

или вариант3:

#include<stdio.h>

int main() {

int i;

for(i=10; i>=0; i- -)

if(i%2==1)

continue;

else

printf(“\n%d”,i);

printf(“\n”);

}

Результат работы этих программ (всех трех вариантов) будет одинаков. Проанализируйте все три варианта. Первый вариант выглядит предпочтительнее. Он более выразителен и понятен.

Выводы:

Выражение1 Инициализация служит для объявления величин, используемых в цикле и присвоения им начальных значений. Несколько операторов пишутся через запятую. Областью действия переменных, объявленных в части инициализации, является цикл. Инициализация выполняется один раз в начале исполнения цикла.

Логическое Выражение 2 определяет условие выполнения цикла. Если его результат – true, цикл выполняется. Цикл for реализован как цикл с предусловием.

Выражение3 Модификация выполняется после каждой итерации цикла и служит обычно для изменения параметров цикла. Здесь можно записать несколько операторов через запятую.

Лабораторная работа по циклам состоит из двух заданий. Первое задание лабораторной работы 3_1 посвящено использованию циклов для построения таблицы значений функции. Второе задание лабораторной работы 3_2 вычислению по рекуррентным формулам.

Пример циклической программы Построение таблицы значений функции

Постановка задачи:

Пусть функция имеет вид у=.

Рабочий набор исходных данных: N=5, a=3, xn=4, xk =8.

Необходимо построить таблицу значений функции для 5 значений аргумента от xn до xk.

Анализ задачи

Для решения поставленной задачи удобно воспользоваться циклом for., так как точно известно количество повторений цикла (которое совпадает с количеством точек таблицы N=5).

Текущее значение x будет изменяться от xn до xk. Для определения шага dx при переходе от одного текущего значения x к следующему значению воспользуемся формулой:

dx=(xk-xn)/(n-1)

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

b=sqrt(a+1)

Текущее значение x при каждой новой итерации цикла будет меняться, увеличиваясь на величину dx, но при первом вхождении в цикл текущему значению x должно быть присвоено начальное значение xn. Это следует сделать до вхождения в цикл:

x=xn

В теле цикла при каждой итерации будет вычислено значение функции y для очередного значения аргумента x , сразу же полученный результат будет выведен на печать. Одна строка таблицы готова. Но прежде чем вернуться в начало цикла для выполнения новой итерации необходимо изменить текущее значение аргумента, увеличив его на величину dx.

Программа построения таблицы значений функции имеет вид:

// табулирование функции

#include<stdio.h>

#include<math.h>

#define XN 4.0

#define XK 8.0

#define A 3.0

int main(){

int n;

float dx,b,x,y;

printf(“введите количество точек таблицы n=”);

scanf(“%d\n”,&n);

printf("таблица значений функции:\n\n");

b=sqrt(A+1);

dx=(XK-XN)/(n-1);

x=XN; // подготовка цикла

for(n=1; n<=5; n++)

{ y=(cos(sqrt(x))+cos(x))/(b+x);

printf("x=%f y=%f\n",x,y);

x=x+dx;

}

return 0;

}

В этой программе добавлена директива препроцессора #define, которая определяет подстановку в тексте программы:

#define имя подстановочный текст

При любом появлении имени (если оно встречается не в тексте, заключенном в “ ”) и не является частью определения другого имени, имя будет заменяться на соответствующий ему подстановочный текст. Подстановочный текст может быть любой последовательностью символов, среди которых могут быть не только цифры. Эти имена рекомендуется писать большими буквами, чтобы зрительно их можно было отличить от имен переменных и функций.. Это – именованные константы , а не переменные, поэтому для них нет описания.

Варианты заданий к работе №3_1

Циклические программы. Построение таблицы значений функций

Требуется решить на ЭВМ задачу вычисления N значений функции y =f(x) для ряда равноотстоящих значений аргумента x , начиная от значения x=xn до значения x=xk включительно. Функция y=f(x) зависит от параметра a. Результаты вычислений следует оформить в виде таблицы, снабженной заголовком. В таблице 3_1 для каждого варианта задан вид функции y=f(x) и рабочий набор данных.

Таблица 3.1

N

Вид функции y=f(x)

Рабочий набор исходных данных

N

a

1

15

1

0,2

0,5

2

10

0,5

-1,3

1

3

12

2

0,3

0,35

4

16

1

2

3

5

12

10

2

6

6

15

0,5

1

2

7

12

1

2

3

8

15

1,5

1

2,5

9

10

0,1

4,2

6

10

8

-2,5

-1,9

-0,9

11

10

1,1

1

2

12

12

3

2

3

13

15

2

1,5

2,9

14

10

3

1,5

3,5

15

12

3

2

3,5

16

15

1,5

1

2,5

17

10

2

2,5

3,5

18

12

2

0

5

19

20

4

1

10

20

15

2

1

5

21

10

1,5

1

4

22

15

2

0

1

23

18

1,5

2

3,5

24

15

1,2

0,1

0,25

25

12

0,5

-p

+p

26

15

1,5

2

4

27

20

2

1

2,5

28

12

2,5

-1

1

29

15

6

2

5

30

16

2

0

1

31

20

3

4

8

Прмер циклической программы. Вычисления по рекуррентным формулам

Рассмотрим возможность применения циклов для вычисления по рекуррентным формулам.

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

Функция y=5x+ при n=3 и x=5

Программа, реализующая вычисление функции y:

#include<stdio.h>

#include<math.h>

#define N 3

#define X 5

int main() {

int k,y,znac,s=0;

znac=1;

for(k=1;k<=N;k++) {

s+=znac*(k+1)*(k+1);

znac=-znac;

}

y=5*X+s;

printf("y=%d",y);

getch();

return 0;

}

Переменная k- параметр цикла( по сути счетчик цикла).

Переменная y выделена для хранения результата работы нашей программы.

Переменная znac обеспечит знакопеременность ряда.

Как ни сложна была бы вычисляемая вами функция, цикл потребуется только для вычисления самой суммы , поэтому вычисление суммы надо выделить в отдельное производство и оформить его в виде цикла. Для этого введем промежуточную переменную s=, в которой и будем накапливать слагаемое за слагаемым нашу сумму. До входа в цикл значение переменной s обнулим. Под знаком суммы стоит множитель , что делает ряд знакопеременным. Для нечетных к знак дает минус, для четных к знак становится плюсом. Вводим переменную с именем znac и для первого слагаемого делаем его положительным znac=1. Перед возвращением на следующую итерацию знак меняем.

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

Обратите на маленькие изменения в программе. Вместо переменной с именем s ввели переменную с именем p.(хотя конечно имя переменной не играет никакой роли, и мы могли бы оставить старое имя s). Важно то, что до входа в цикл для того, чтобы не нарушить рекуррентность формулы для расчета произведения при первом прохождении цикла мы присвоили ей значение eдиница(p=1)

#include<stdio.h>

#include<math.h>

#define N 3

#define X 5

int main() {

int k,y,znac,p=1;

znac=1;

for(k=1;k<=N;k++) {

p*=znac*(k+1)*(k+1);

znac=-znac;

}

y=5*X+p;

printf("y=%d",y);

return 0;

}

Варианты заданий к работе №3_2

Циклические программы. Вычисления по рекуррентным формулам

Таблица 3.2

Номер варианта

Функция

Рабочий набор

n

х

1

75

3,5

2

30

8

3

80

5,3

4

100

1,5

5

11

0,8

6

25

1, 8

7

10

0,8

8

20

4,5

9

25

-2,1

10

55

3,2

11

20

3,1415

12

15

0,4

13

30

9

14

15

1,2

15

35

1,1

16

25

1,2

17

20

0,8

18

20

0,5

19

55

0,5

20

15

1,5

21

25

0,35

22

40

0,5

23

45

0,4

24

40

10

25

25

1,5

26

45

2,4

27

25

0,75

28

40

0,85

29

40

5

30

12

4,75

31

20

4,75

Анализ программы по совместному использованию оператора switch и циклов

После выполнения работ с использованием базовых конструкций следования, разветвления и циклов проанализируйте пример работы оператора switch c различными видами циклов while, do while и for.

В зависимости от введенного символа (w, d и f) оператор switch должен переключить вас на работу с соответствующим видом цикла. Программа должна с помощью различных видов цикла вычислить значение функции y=x*.

Проведенный анализ поможет вам закрепить материал по использованию оператора switch,а также еще раз провести сравнение трех видов цикла.

Текст программы

#include<stdio.h>

int main() {

float x=1.8,y,s=0,p=1;

int n=5,k;

char ch;

printf(“enter symbol ch:\n”);

scanf(“%c”,&ch);

switch(ch) {

case ‘f’:

for(k=1;k<=n;k++) {

s+=1/k;

p*=(k+x)/(k+1);

}

y=x*s+p;

printf(“\ny=%7.2f”,y);

break;

case ‘d’:

k=1;

do {

s+=1/k;

p*=(k+x)/(k+1);

k++;

}

while(k<=n);

y=x*s+p);

printf(“\ny=%7.2f”,y);

break;

case ‘w’:

k=1;

while(k<=n) {

s+=1/k;

p*=(k+x)/(k+1);

k++;

}

y=x*s+p);

printf(“\ny=%7.2f”,y);

break;

default: printf(“\ntry again”);

}

return 0;

}

Выводы

  • Циклы используются для организации многократно повторяющихся вычислений.

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

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

  • По синтаксису языка в теле цикла разрешено иметь только один оператор. Если в теле цикла более одного оператора, то тело цикла заключается в фигурные скобки(блок).

  • Помните, что операторы цикла взаимозаменяемы, но одни являются циклами с предусловием (while,for), другие циклами с постусловием (do while). Последний хотя бы один раз, но будет выполнен обязательно. Цикл while используют, когда число повторений цикла заранее не известно. Оператор for используют для организации циклов со счетчиками.

  • Выражения, стоящие в круглых скобках операторов do while, while и for принимают значения true-истина, или false-ложь.

  • Выражения, стоящие в скобках после ключевого слова switch и константные выражения в case должны быть целочисленного типа.

  • В конце оператора switch рекомендуется ставить веточку default.

  • После каждой из веточек case желательно использовать оператор break.

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

Задания для самостоятельной работы

Для закрепления пройденного материала и подготовки к экзамену выполните следующие задания:

Задание 1

Составить программу, которая вычисляет и выводит на экран монитора таблицу “n” значений функции y на интервале от xn до xk:

y= a*lg|x+15| при x<-3

при -3<=x<7

при x>=7

a=-3,7.

Значения xn, xk и количество точек таблицы n вводятся с клавиатуры.

Задание 2

Составить программу, которая вычисляет и выводит на экран монитора таблицу “n” значений функции y на интервале от xn до xk:

y= a*x2 при x<-5

при -5<=x<1

ln|x-3| при x>=1

a=1,37.

Значения xn, xk и количество точек таблицы n вводятся с клавиатуры.

Задание 3

Написать программу табулирования функции, заданной следующим выражением:

где m=8,xn=1, xk=7, n=15 (количество точек)

Задание 4

Написать программу табулирования функции, заданной следующим выражением:

где m=8,xn=1, xk=7, n=15 (количество точек)

Задание 5

Написать программу табулирования функции, заданной следующим выражением:

где m=8, xn=2 xk=8, n=10(кол-во точек табуляции)

Контрольные вопросы по разветвлениям и циклам

1. Какие виды циклов вам известны?

2.В каких ситуациях используется тот или иной вид цикла?

3.Что принято называть параметром цикла?

4.Можно ли вне цикла использовать значение параметра цикла?

5.Какие управляющие структуры используются для реализации разветвляющихся программ?

6.В каких ситуациях удобнее пользоваться оператором switch?

Соседние файлы в предмете Информатика