Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лабораторная работа 4.doc
Скачиваний:
8
Добавлен:
09.11.2018
Размер:
331.26 Кб
Скачать

ЛАБОРАТОРНАЯ РАБОТА № 4

Операторы цикла

Цель работы – овладеть практическими навыками разработки, программирования вычислительного процесса с использованием операторов цикла, получить дальнейшие навыки по отладке и тестированию программы.

Операторы while и do-while

Пример 1. Исправить программу из лаб. 3, пример 4 так, чтобы можно было делать новые вычисления не выходя из программы.

Для организации повторных вычислений лучше всего использовать цикл do-while:

Начальные установки

Вычисления

нет

да

Исправляем программу:

int main(int argc, char* argv[])

{

double a, b, c, d; // a, b, c - переменные для коэффициентов уравнения.

double x1=1, x2=1; // x1, x2 - переменные для корней уравнения.

char key;

char sIn1[] = "Введите коэффициенты уравнения >";

char sIn2[] = "Повторить?";

char sOut1[] = "Корни :\n x1= %f\nx2= %f\n";

char sOut2[] = "Уравнение не имеет действительных корней. \n";

char sOut3[] = "Уравнение имеет один корень x1= %f\n";

char sOut4[] = "Любое число является корнем уравнения\n";

char sOut5[] = "Уравнение не имеет решений\n";

CharToOem (sIn1, sIn1);

CharToOem (sIn2, sIn2);

CharToOem (sOut1, sOut1);

CharToOem (sOut2, sOut2);

CharToOem (sOut3, sOut3);

CharToOem (sOut4, sOut4);

CharToOem (sOut5, sOut5);

do

{

printf(sIn1);

scanf("%lf %lf %lf", &a, &b, &c);

if (a != 0) // Если выражение a != 0, то уравнение квадратное.

{

d = b * b - (4 * a * c); // Вычисляем дискриминант.

if (d >= 0) // Если дискриминант >= 0, то

{

d = sqrt(d); // уравнение имеет два корня.

x1= (-b + d)/(2 * a);

x2 = (-b - d)/(2 * a);

printf(sOut1, x1, x2);

}

else // Если дискриминант < 0, то действительных корней нет.

printf(sOut2);

} // Случай a != 0 рассмотрен.

else // Случай a = 0. Уравнение линейное и имеет вид bx + c = 0

{

if (b != 0) // Случай, когда b не равен нулю.

printf(sOut3, x1);

else // Случай, когда b = 0

{

if ( c == 0) // Случай a = 0, b = 0, c = 0.

printf(sOut4);

else // Случай a = 0, b = 0, c != 0.

printf(sOut5);

}

}

printf(sIn2);

key = getch();

} while (key == ‘y’);

}

Пример 2. Ввести целое число и определить, сколько в нем цифр.

Для решения этой задачи обычно применяется такой алгоритм. Число делится на 10 и отбрасывается остаток, и так до тех пор, пока результат деления не равен нулю. С помощью специальной переменной (она называется счетчиком) считаем, сколько раз выполнялось деление столько цифр и было в числе. Понятно, что нельзя заранее определить, сколько раз надо разделить число, поэтому надо использовать цикл с условием.

int main(int argc, char* argv[])

{

int N; // число, с которым работаем

int count=0; // переменная-счетчик

char sOut5[] = "В этом числе %d цифр\n";

CharToOem (sOut5, sOut5);

printf ( "N = " );

scanf ( "%d", &N ); // ввод N с клавиатуры

while ( N > 0 ) // заголовок цикла "пока N > 0"

{ // начало цикла (открывающая скобка)

N /= 10; // отсекаем последнюю цифру

count ++; // увеличиваем счетчик цифр

} // конец цикла (закрывающая скобка)

printf ( sOut5, count);

getch();}

Пример 3. С клавиатуры вводится целое число. Составить программу, которая определяет наименьшую и наибольшую цифру этого числа.

Для решения этой задачи используем подобный алгоритм. Кроме счетчика объявляем переменные, куда будем помещать мах и мин.значения

int main(int argc, char* argv[])

{

int N; // число, с которым работаем

int count=0; // переменная-счетчик

int max, min;

char sIn[] = "Введите число >";

char sOut[] = "В этом числе %d цифр, max = %d, min = %d\n";

CharToOem (sIn, sIn);

CharToOem (sOut, sOut);

printf (sIn);

scanf ("%d", &N); // ввод N с клавиатуры

N = abs(N);

max = min = N % 10;

while (N > 0) // заголовок цикла "пока N > 0"

{ // начало цикла (открывающая скобка)

if (max < N%10) max = N%10;

if (min > N%10) min = N%10;

N /= 10; // отсекаем последнюю цифру

count ++; // увеличиваем счетчик цифр

}

printf (sOut, count, max, min);

getch(); }

Цикл for

Пример 4. Для ряда, члены которого вычисляются по формуле ,

подсчитать сумму членов ряда с точностью до EPS = 0.000001 и сумму первых COUNT = 10 членов ряда.

Алгоритм решения:

Процесс подсчета суммы членов ряда должен быть итерационным, поэтому следует повторять вычисления по одной и той же формуле при значениях n = 0, 1, 2, ... . В каждой итерации цикла следует выполнять вычисления по заданной формуле для текущего значения n, т.е. подсчитывать очередной член ряда. Полученное значение следует прибавлять к переменной, которая представляет сумму. Эта переменная в каждой итерации будет содержать в себе сумму всех уже обработанных членов ряда, следовательно, ее начальное значение (когда ни один член еще не обработан) должно быть 0. После вычисления суммы при значении n = 9 следует вывести значение суммы – это один из результатов программы в соответствии с заданием (берется значение 9, т.к. первый член ряда вычисляется при n = 0, таким образом, десятый – при n  =9). После вычисления каждого члена ряда (но до прибавления его значения к сумме) следует сравнить полученное значение с заданным пределом точности. Из-за того, что значение члена ряда может быть как положительным, так и отрицательным, при сравнении следует использовать абсолютное значение. Если абсолютное значения члена ряда меньше предела точности, следует закончить вычисления: выйти из цикла напечатать значение суммы и завершить программу.

Алгоритм вычисления 2n : Для выполнения возведения в степень можно применить библиотечную функцию pow(x,y) . Но есть возможность получения этого значения более эффективным способом. В каждой следующей итерации цикла значение этого выражения вдвое больше, чем в предыдущей. Так что, будет целесообразно выделить отдельную переменную для сохранения значения 2n. Ее начальное значение должно быть 20 = 1, а в конце каждой итерации оно должно удваиваться.

Алгоритм вычисления (-1)n : В этом случае также нецелесообразно применять функцию возведения в степень. Значение этого выражения будет 1 при четных значениях n и –1 – при нечетных. Так что, можно выделить переменную для сохранения значения этого выражения. Ее начальное значение должно быть (-1)0=1, а в конце каждой итерации оно должно менять знак на противоположный.

Схема алгоритма показана на рисунке.

Определение переменных программы:

n - параметр цикла; по условиям задачи это – целое число; поскольку заранее неизвестно, сколько итераций цикла будет нужно для достижения предела точности, объявим его как "длинное целое": long n;

term - значение текущего члена ряда. Объявим его как: double term;

sum - текущее значение суммы ряда с начальным значением 0: double sum=0;

k2 - переменная для сохранения текущего значения 2n с начальным значением 1. Она должна быть "длинным целым" - из тех же соображений, что и n: long k2=1;

k1 - переменная для сохранения текущего значения (-1)n с начальным значением 1. Для нее достаточно быть "коротким целым": short k1=1;

Разработка текста программы

1. Объявляем константы с помощью директивы препроцессора #define. Включаем заголовочные файлы с описанием библиотечных функций, используемых в программе.

2. Объявляем переменные и присваиваем им необходимые начальные значения.

3. Цикл можно организовать разными способами, но в данном случае удобнее использовать оператор цикла for. По схеме алгоритма видно, что выход из цикла происходит в середине его тела – после вычисления члена ряда, но до добавления его значения к сумме, следовательно придется использовать оператор break. Поэтому задавать условие в самом операторе цикла необязательно, задаем только начальное значение n и действия в конце каждой итерации: n++ – инкремент параметра цикла, k2 *= 2 – вычисление очередного значения 2n, k1 = –k1 – вычисление очередного значения –1n.

4. В теле цикла вычисляем значение текущего члена ряда не забывая о том, что n, k1 и k2 – переменные целого типа, т.е. и их сумма, произведение и т.д. будут проводиться по правилам целочисленной арифметики, а нужно – по правилам вещественной, поэтому ставим оператор преобразования типа (double).

5. Проверяем, достигнут ли предел точности (с помощью оператора if), при этом сравниваем абсолютное значение term (функция fabs() служит для получения абсолютного значения переменной типа double). Если предел не достигнут, добавляем значения очередного вычисленного члена к сумме, иначе выходим из цикла (оператор break).

6. Проверяем, достигла ли переменная n значения 9. Организуем это с помощью еще одного условного оператора if и при выполнении условия выводим на печать значение суммы. Поскольку при невыполнении условия не делается ничего, часть else для этого оператора не нужна.

7. Завершаем цикл. После выхода из цикла выводим на печать окончательное значение суммы и завершаем программу.

При вызове функции printf() всегда возникает проблема форматизации вывода. Мы включили в формат текст, который поясняет вывод, а значение переменной sum выводим по спецификации %10.7lf. Тип спецификации соответствует типу переменной - double, а числовые параметры мы выбрали произвольно, поскольку в задании не оговорены требования к точности вывода. Перед точкой мы оставляем 2 позиции - для знака и целой части (которая должна быть 0), после точки - 7 позиций, что на 1 превышает точность заданного предела точности.

Полный текст программы приведен ниже.

#define EPS 0.000001 // Предел точности

#define COUNT 10 // Кол-во заданных первых членов ряда

#include <stdio.h>

#include <math.h>

int main(int argc, char* argv[])

{

int n; // параметр цикла

double sum=0; // сумма членов ряда

double term; // значение текущего члена

int k2=1; // для вычисления 2^n

short k1=1; // для вычисления -1^n

for (n=0; ; n++, k2*=2, k1=-k1)

{

term = (double)k1 * (n + 1.0)/(n * n + k2); // вычисл. очередного члена

if (fabs(term) >= EPS) // проверка достижения предела точности

sum+=term; // если не достигнут - накопление суммы

else break; // если достигнут - выход из цикла

if (n == COUNT - 1) // если 10 членов - вывод суммы

printf("Сумма 10 членов ряда = %10.7lf\n",sum);

} // конец основного цикла

printf("Полная сумма ряда = %10.7lf\n",sum); // вывод окончательной суммы

return 0;

}

Результаты работы программы

     При работе программы на экран были выведены такие результаты:

Сумма 10 членов ряда = 0.5600899

Полная сумма ряда = 0.5663245