Циклы по счетчику

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

При организации цикла по счетчику необходимо:

1) выделить повторяющиеся действия и записать их в общем виде;

2) выбрать управляющую переменную цикла. Это может быть какая-либо величина, имеющаяся в постановке задачи, либо используемая специально в качестве счетчика;

3) определить параметры цикла, т.е. начальное и конечное значения управляющей переменной и шаг ее изменения.

Пример 2.1. Вычислить s = 1 + 2 + 3 + … +100.

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

s = s + i, где i = 1, 2, 3, ... , 100.

Таким образом, в качестве управляющей переменной цикла в данном случае можно использовать сам член суммы, который изменяется в заданных пределах (от 1 до 100) с заданным шагом 1. Тогда программа будет иметь следующий вид:

using System;

namespace ConsoleApplication3

{

class Program

{

static void Main(string[] args)

{

int i, s = 0;

for (i = 1; i <= 100; i = i + 1)

s = s + i;

Console.WriteLine("s = {0}", s);

Console.ReadKey();

}

}

}

Результат выполнения программы:

Пример 2.2. Вычислить сумму четных чисел от 2 до 20.

Здесь требуется организация цикла по счетчику с управляющей переменной, например k, изменяющейся с шагом 2 от 2 до 20:

using System;

namespace ConsoleApplication1

{

class Program

{

static void Main()

{

int k, s = 0;

for (k = 2; k <= 20; k = k + 2)

s = s + k;

Console.WriteLine("s= {0}", s);

Console.ReadKey();

}

}

}

Или

using System;

namespace ConsoleApplication1

{

class Program

{

static void Main(string[] args)

{

int k = 2, s = 0;

do

{

s = s + k;

k = k + 2;

} while (k <= 20);

Console.WriteLine("s = {0}", s);

Console.ReadKey();

}

}

}

Пример 2.3. Вычислить s = 3 + 32 + 33 + … + 38.

На каждом шаге алгоритма необходимо прибавлять к сумме очередное слагаемое: (s = s + 3i), где i = 1, 2, 3, ... , 8.

Вспомним, что операция возведения в степень в языке C# отсутствует, поэтому следующий член суммы будем получать из предыдущего домножением его на 3. В качестве управляющей переменной цикла можно использовать показатель степени, изменяющийся в заданных пределах от 1 до 8 с заданным шагом, равным 1. Программа, таким образом, будет иметь следующий вид (здесь и далее приводится только алгоритмическая часть проекта):

int s = 0, a = 1;

for (int i = 1; i <= 8; i = i + 1)

{

a = a * 3;

s = s + a;

}

Console.WriteLine("s = {0}", s);

Console.ReadKey();

Замечание. Выражение для получения очередного члена последовательности из предыдущего называется рекуррентной формулой.

Пример 2.4. Вычислить s = 5/8 + 7/10 + ... + 31/34.

Для организации цикла в этом случае можно использовать числитель, изменяющийся от 5 до 31 с шагом 2, а знаменатель выразить через числитель (он отличается от числителя на 3):

double s = 0;

for (int a = 5; a <= 31; a = a + 2)

{

s = s + a / (a + 3.0);

}

Console.WriteLine("s = {0}", s);

Console.ReadKey();

Замечание. При делении целого на целое дробная часть теряется (результат получается целым). Поэтому при вычислении знаменателя второе слагаемое записано в виде вещественного числа. Знаменатель будет теперь иметь тип double, и результат деления будет иметь тип double.

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

Для организации цикла в данном примере можно использовать специальную переменную (счетчик), определяющую номер итерации. Для определения общего количества повторений цикла (n) можно использовать формулу

n = (iконiнач)/h + 1.

В данном случае при iкон = 31, iнач = 5, h = 2 получаем n = 14. Тогда программа будет иметь вид

double s = 0, a;

int n;

double xh = 5, xk = 31, h = 2;

a = xh;

n = (int)((xk - xh) / h + 1);

for (int i = 1; i <= n; i = i + 1)

{

s = s + a / (a + 3);

a = a + h;

}

Console.WriteLine("s = {0}", s);

Console.ReadKey();

Здесь при вычислении n использовано явное преобразование типа указанием типа в скобках перед выражением, так как результат метода Round (округление) имеет тип double.

Пример 2.5. Вычислить .

double s = 0.0, a;

int i, p = 1;

for (i = 1; i <= 25; i = i + 1)

{

p = -p;

a = p * 2 * i / (i * i + 2.0);

s = s + a;

}

s = (2.0 / 3.0) * s;

Console.WriteLine("{0:f4}",s);

Console.ReadKey();

Замечание. В программе использован тот же прием согласования типов, что и в примере 2.4. Порядок вычислений и тип результата операций в выражении правой части при вычислении члена суммы a следующий: вычисляется p ´ 2 – тип результата int, результат этой операции умножается на i, тип результата int, вычисляется знаменатель (выражение в скобках) в следующем порядке: вычисляется i ´ i - результат операции имеет тип int, к этому результату прибавляется вещественное число 2.0 (по умолчанию типа double), знаменатель после вычисления имеет тип double. Таким образом, значение выражения правой части имеет тип double.

Пример 2.6. Получить таблицу значений функции при изменении x в пределах от xh = –2,5 до xk = 2,5 с шагом h = 0,5.

const double xh = -2.5, xk = 2.5, h = 0.5;

double x, y;

int i, n;

n = (int)((xk - xh) / h + 1);

x = xh;

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

{

y = Math.Pow(x, 2) + 0.5 * x;

Console.WriteLine("x = {0:f2}\ty = {1:f2}", x, y);

x = x + h;

}

Console.ReadKey();

Замечания:

1. Для определения количества значений аргумента при его изменении в пределах от xh до xk c шагом h использована формула n =(xk - xh)/h + 1.В программе для получения в качестве n целого значения использовано явное преобразование типа указанием его в скобках перед выражением.

2. Для вычисления использован метод Pow класса Math.

3. Наличие символа \t в строке формата обеспечивает табуляцию при выводе каждого значения y, что обеспечивает большую наглядность результата. (Этого эффекта можно добиться и другими способами. Предложите их самостоятельно.)

Второй вариант. Используется цикл do:

const double xh = -2.5, xk = 2.5, h = 0.5;

double x, y;

x = xh;

do

{

y = Math.Pow(x, 2) + 0.5 * x;

Console.WriteLine("x = {0:f2}\ty = {1:f2}",

x, y);

x = x + h;

}

while (x < xk + 0.0001);

Console.ReadKey();

Здесь при проверке условия while сравнение текущего значения x осуществляется с величиной несколько большей верхней границы его изменения. Это связано с особенностями представления в памяти компьютера вещественных чисел. Вещественные числа представляются неточно, и в результате многократного выполнения арифметических операций может накопиться ошибка, так что последнее значение x может быть несколько больше xk и при отсутствии второго слагаемого в условии не попадет в таблицу.

Пример 2.7. Вычислить p = n! при n = 8.

Вычисление факториала можно организовать в цикле, домножая каждый раз значение p на очередной сомножитель:

const int n = 8;

int p = 1;

for (int i = 2; i <= n; i++)

{

p = p * i;

}

Console.WriteLine("p = {0:d}", p);

Console.ReadKey();