- •Основы программирования на языке Паскаль
- •Часть 1. Основы языка Паскаль 2
- •Часть 2. Элементы профессионального программирования на Паскале 44
- •От автора
- •Часть 1. Основы языка Паскаль
- •1. Алгоритм и программа
- •1.1. Алгоритм
- •1.2. Свойства алгоритма
- •1.3. Формы записи алгоритма
- •1.4. Программа и программное обеспечение
- •1.5. Этапы разработки программы
- •2. Данные в языке Паскаль
- •2.1 Константы
- •2.2 Переменные и типы переменных
- •3. Арифметические выражения
- •4. Линейный вычислительный процесс
- •4.1 Оператор присваивания
- •4.2 Оператор ввода
- •4.3 Оператор вывода
- •4.4 Управление выводом данных
- •4.5 Вывод на печать
- •5. Структура простой программы на Паскале
- •6. Компилятор и оболочка Turbo Pascal
- •7. Разветвляющийся вычислительный процесс и условный оператор
- •7.4. Короткий условный оператор
- •If логическое_выражение then оператор1;
- •7.5. Полный условный оператор
- •If логическое_выражение then оператор1
- •7.7. Вложенные условные операторы
- •7.9. Примеры программ с условным оператором
- •8. Директивы компилятора и обработка ошибок ввода
- •9. Оператор цикла. Циклы с предусловием и постусловием
- •10. Цикл со счетчиком и досрочное завершение циклов
- •11. Типовые алгоритмы табулирования функций, вычисления количества, суммы и произведения
- •11.1 Алгоритм табулирования
- •11.2 Алгоритм организации счетчика
- •11.3 Алгоритмы накопления суммы и произведения
- •12. Типовые алгоритмы поиска максимума и минимума
- •13. Решение учебных задач на циклы
- •14. Одномерные массивы. Описание, ввод, вывод и обработка массивов на Паскале
- •15. Решение типовых задач на массивы
- •Часть 2. Элементы профессионального программирования на Паскале
- •16. Кратные циклы
- •16.1 Двойной цикл и типовые задачи на двойной цикл
- •16.2 Оператор безусловного перехода
- •17. Матрицы и типовые алгоритмы обработки матриц
- •18. Подпрограммы
- •18.1 Процедуры
- •18.2 Функции
- •18.3 Массивы в качестве параметров подпрограммы
- •18.4 Открытые массивы
- •19. Множества и перечислимые типы
- •20. Обработка символьных и строковых данных
- •20.1. Работа с символами
- •20.2 Работа со строками
- •21. Текстовые файлы
- •21.1 Общие операции
- •21.2 Примеры работы с файлами
- •21.3 Работа с параметрами командной строки
- •22. Записи. Бинарные файлы
- •23. Модули. Создание модулей
- •23.1. Назначение и структура модулей
- •23.2. Стандартные модули Паскаля
- •24. Модуль crt и создание простых интерфейсов
- •25. Модуль Graph и создание графики на Паскале
- •Приложение 1. Таблицы ascii-кодов символов для операционных систем dos и Windows
- •Приложение 2. Основные директивы компилятора Паскаля
- •Приложение 3. Основные сообщения об ошибках Паскаля
- •Приложение 4. Дополнительные листинги программ
- •Приложение 5. Расширенные коды клавиатуры
- •Ascii‑коды
- •Расширенные коды
- •Приложение 6. Правила хорошего кода
- •Приложение 7. Рекомендуемая литература
13. Решение учебных задач на циклы
Используя полученные навыки работы с типовыми алгоритмами, рассмотрим несколько учебных задач различных типов.
На практике нередко встречаются задачи, для которых число шагов цикла заранее неизвестно и не может быть вычислено. Как правило, в этом случае расчетный цикл работает до выполнения некоторого условия, определяющего достижение требуемого результата. Приведем пример подобной задачи.
Пр. Задана функция и ее разложение в ряд:
n=0,1,2,… (здесь n! обозначает факториал числа n, равный 1*2*3*….*n; при этом 0!=1). Найти число элементов ряда k, требуемое для достижения заданной точности ε.
Это – типичная задача на ряды. С ростом n слагаемые становятся все меньше, равно как и модуль разности между двумя соседними слагаемыми. Поэтому под достижением заданной точности будем понимать выполнение условия где Sn, Sn-1 – суммы ряда, вычисленные на текущем и предыдущем шагах цикла, ε задается малым числом, от 10-6 и ниже. Для вычисления x2n введем переменную xn, которую на каждом шаге цикла будем домножать на x2, аналогично, для вычисления текущего значения факториала используем переменную nf. Иной подход потребовал бы большого количества повторных вычислений на каждом шаге цикла, плюс был бы чреват большими потерями точности. Для вычисления (-1)n было бы странно использовать формулу ax=exln a – вполне достаточно завести целочисленную переменную znak, равную 1, которая на каждом шаге цикла будет менять свое значение на противоположное оператором znak:=-znak;. Кроме того, так как требуемое число шагов заранее неизвестно, используем для всех основных переменных более точный тип double вместо real.
Реализуем все сказанное в следующей программе:
{$N+} {Директива режима совместимости с 80287 - для использования double}
var x,sn,sn1,xn,nf,eps:double;
k,n:longint;
znak:integer;
begin
writeln ('Введите значение x для разложения в ряд:');
read (x);
writeln ('Введите требуемую точность:');
read (eps);
sn1:=0;
sn:=0;
k:=0;
n:=0;
xn:=1;
nf:=1;
znak:=1;
repeat
sn1:=sn; {Текущая сумма стала предыдущей для следующего шага}
sn:=sn+znak*xn/nf; {Выполняем шаг цикла}
{Меняем переменные для следующего шага:}
znak:=-znak;
xn:=xn*sqr(x);
nf:=nf*(n+1)*(n+2);
n:=n+2;
k:=k+1;
until abs(sn1-sn)<eps;
writeln ('Точное значение функции=',cos(x):20:16);
writeln ('Предыдущая сумма=',sn1:20:16);
writeln ('Текущая сумма=',sn:20:16);
writeln ('Число шагов=',k);
reset (input); readln;
end.
До главы "Графика" еще далеко, но даже в обычном текстовом режиме работы можно наглядно проиллюстрировать результаты своих расчетов. Рассмотрим в качестве примера задачу:
Пр. Сформировать на экране изображение функции
f(x)= cos(x)+ln(x)
на интервале [1,5] с шагом 0.2.
Программа с подробными комментариями приводится ниже:
var x,y, { Значение аргумента и функции }
a,b, { Интервал }
ymin,ymax:real; { Минимальное и максимальное Y }
cy, { Позиция столбца на экране }
i:integer; { Счетчик для цикла for }
begin
a:=1;
b:=5;
{ Первый цикл нужен, чтобы определить минимальное и максимальное
значение функции на заданном интервале }
x:=a; { Начинаем с левой границы }
ymin:=1e20; ymax:=1e-20; { Минимуму присваиваем большое число,
максимуму - маленькое }
while x<=b do begin { Пока x не превысило правой границы }
y:=cos(x)+ln(x); { считаем очередное значение функции }
if y<ymin then ymin:=y { Ищем минимум }
else if y>ymax then ymax:=y; { Ищем максимум }
x:=x+0.2; { Переходим к следующему x }
end; { Конец первого цикла }
{ Во втором цикле обработки можно выводить на экран значения функции }
x:=a;
while x<=b do begin { Пока x не превысило правой границы }
y:=cos(x)+ln(x); { считаем очередное значение функции }
cy:=Round ( 8+(y-ymin)*(70/(ymax-ymin)) );
{ Чтобы пересчитать y из границ [ymin,ymax] в границы [8,78] (столбцы
экрана, в которые выводим график), используем формулу
78 - 8
cy= 8 + (y-ymin) * -----------
ymax - ymin
Теперь в переменной cy - нужный нам столбец экрана }
writeln; { Переходим к новой строке на экране }
write (x:7:3,' '); { Выводим значение x и пробел }
for i:=8 to cy do write ('*'); { Рисуем звездочками значение y }
x:=x+0.2; { Переходим к следующему x }
end; { Конец второго цикла }
end.
Пр. Проверить, является ли введенное положительное целое число N простым.
Очевидно, что простое число делится без остатка только на единицу и само на себя. В цикле последовательно проверим остатки от деления N на числа 2,3,…,N-1. Если найден хотя бы один остаток, равный нулю, число не является простым и дальнейшие проверки бессмысленны. Обратите внимание на использование логической переменной-флага s в этой программе.
var n,i:longint;
s:boolean;
begin
write ('N=');
readln (n);
s:=true;
for i:=2 to n-1 do
if n mod i = 0 then begin
s:=false;
break;
end;
if s=true then writeln ('простое')
else writeln ('НЕ простое');
end.