1.3.Определения элементов цикла
Приведем формальные определения терминов, показанных ранее на примерах.
Инвариантом называется условие, которое выполняется на каждом шаге цикла, включая значение переменных до начала выполнения цикла и после выполнения цикла. Это условие может быть записано в виде математического отношения, связывающего между собой переменные, участвующие в цикле. В некоторых случаях, когда математическое описание громоздко, его можно сформулировать и обычным языком.
Предусловием называется состояние переменных перед выполнением цикла. Это условие должно совпадать с инвариантом, в который подставили некоторые конкретные значения переменных. Во многих случаях предусловие цикла не совпадает с данными задачи. В таких случаях нужно произвести некоторые действия (которые чаще всего заключаются в присвоении значений переменным), которые приводят к выполнению предусловия. Эти действия называются инициализацией цикла.
Постусловием называется состояние переменных после выполнения цикла. Это условие должно также должно совпадать с инвариантом, в который подставили некоторые конкретные значения переменных. При этом оно должно соответствовать условию решения задачи. В некоторых случаях нужно сделать еще несколько действий вне цикла для достижения условия решения.
Частью постусловия является условие окончания (или условие выполнения) цикла. Эта часть должна дать возможность определить, что инвариант пришел к состоянию предусловия.
Телом цикла называются действия внутри цикла. Эти действия должны, во-первых, приблизить условие окончания цикла, во-вторых, сохранить инвариант на каждом шагу. Обычно тело цикла записывается по примерно следующему алгоритму: определяется шаг цикла, который приближает предусловие, затем определяются действия, которые обеспечивают условие инварианта после шага цикла.
После определения всех условий цикла и его тела вместе с шагом его можно записать на языке высокого уровня.
1.4.Пример формального построения цикла
Рассмотрим задачу. Нужно подсчитать
сумму ряда
.
Остаток ряда, начиная с члена меньше
некоторого параметра eps
нужно отбросить.
Для решения этой задачи нужно построить цикл, на каждом шаге которого прибавлялось бы по одному слагаемому.
На каждом шаге цикла должны быть
справедливы следующие условия (инвариант
цикла). Обозначим за i
номер шага цикла. Тогда слагаемое,
которое нужно прибавить, определяется
по формуле:
.
Переменная, в которой мы будем накапливать
сумму должна попадать под следующее
условие:
.
На нулевом шаге для выполнения инварианта переменные должны иметь следующие значения: i=0; p=1; s=1; – это предусловие цикла.
Цикл нужно закончить, когда p<eps – условие окончание цикла, или цикл должен продолжаться до тех пор, пока p≥eps – условие выполнения цикла.
Определив все условия цикла можно записать тело цикла.
Для того чтобы приблизиться к окончанию цикла, переменную i нужно увеличить:
.
Для того чтобы сохранить инвариант, переменную p нужно изменить следующим образом:
Мы получили два способа вычисления p:
через старое значение i
и через новое
.
Выбор способа зависит от порядка
вычисления, но поскольку вычисление i
удобно проводить как шаг цикла, который
вычисляется после всех операций, то
проще вычислять через старое i.
Выведем формулу для вычисления s:
Теперь можно записать цикл на языке С.
int main()
{
float eps = 0.001;
int i=0;
float s=1, p=1;
for(;p>eps;i++)
{
p=p/(i+1);
s=s+p;
}
printf("e=%f",s);
}
Для простоты записи инициализация переменных цикла выполняется при их объявлении.
