Самостоятельная работа дан прямоугольный контур, по которому двигается точка (координаты противоположных не смежных вершин прямоугольника задаются с клавиатуры)

Задачи:

1. Два мячика двигаются по экрану (один сверху вниз, другой слева направо).

2. Две рожицы двигаются по экрану (одна веселая, другая грустная).

3. Бильярдный шарик двигается по экрану.

4. Броуновское движение.

Управление движением.

Пример: движение шарика только при нажатии стрелок.

Задачи:

1. Шарик двигается, а при нажатии различных клавиш изменяется его направление. скорость, радиус и т.д.

Движение по окружности.

Подпрограммы.

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

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

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

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

Передача данных из основной программы в подпрограмму (входные данные) и возврат результата выполнения подпрограммы осуществляется с помощью параметров.

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

Использование подпрограмм позволяет реализовать один из самых прогрессивных методов программирования - структурное программирование.

Процедура в Паскале

и ее формат.

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

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

Структура процедуры имеет вид:

Procedure имя(список формальных параметров);

(* раздел описаний *)

begin

(* раздел операторов *)

end;

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

В заголовке указывается служебное слово PROCEDURE, за которым следуют имя процедуры и список формальных параметров, заключенные в круглые скобки (если такие имеются). В списке перечисляются имена формальных параметров и их тип. Имя параметра отделяется от типа двоеточием, а параметры друг от друга - точкой с запятой. Если несколько формальных параметров имеют одинаковый тип, тогда их можно перечислить через запятую, а затем указать тип.

Тело процедуры заключается в операторные скобки BEGIN и END, причем после END ставится точка с запятой.

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

Процедура вызывается по ее имени:

имя(список фактических параметров);

Формальные параметры - параметры, определенные в заголовке процедуры.

Фактические параметры - выражения, задающие конкретные значения при обращении к процедуре.

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

Фактические параметры - это параметры, которые передаются процедуре при ее вызове.

Количество и тип формальных и фактических параметров должны в точности совпадать.

Формальные параметры описываются в заголовке процедуры и определяют тип и место подстановки фактических параметров. Формальные параметры делятся на два вида: параметры-переменные и параметры-значения.

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

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

Все переменные программы делятся на глобальные и локальные. Глобальные переменные объявляются в разделе описаний основной программы. Локальные переменные объявляются в процедурах и функциях. Таким образом, локальные переменные «живут» только во время работы подпрограммы.

Пример. Составить программу для вычисления аn: целые числа а и n (n>=0) вводятся с клавиатуры. (составить процедуру для вычисления степени целого числа).

Program ex;

var a, n: integer;

s: longint;

Procedure Degree(x,y: integer; var st: longint);

var i: integer;

begin

st:=1;

for i:=1 to y do st:=st*x;

end;

{ начало основной программы}

begin

writeln(‘введите два числа - основание и показатель степени’);

readln(a,n);

Degree(a,n,s); { обращение к процедуре }

writeln(‘Результат ’,s);

end.

Процедура названа именем Degree. В скобках записан список формальных параметров, то есть перечислены переменные с указанием их типа. Используем три параметра: первый - основание степени, то есть число, которое надо возвести в степень; второй - показатель степени, третий - результат. Первые два формальных параметра - параметры значения, третий - параметр-переменная, и перед ним указано слово var. Все они описаны как целые (x и y - переменные типа integer, st - Longint, так как степенная функция быстро возрастает).

После заголовка процедуры идут разделы описаний. В нашем примере имеется только раздел описания переменных, в котором описывается одна переменная i (счетчик цикла).

Далее идет тело процедуры. Оно начинается служебным словом Begin и заканчивается служебным словом End, после которого стоит точка с запятой (в конце программы после последнего End ставится точка). В теле процедуры вычисляется степень числа x с помощью цикла For.

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

!!!! Процедура вызывается как оператор, состоящий из имени процедуры. В круглых скобках записываются фактические параметры. В нашем примере формальные параметры x, y и st принимают значения фактических параметров a, n и s соответственно. После завершения работы процедуры переменные a и n сохранят те же значения, что и при вызове, а s получит новое значение.

Пример 2: Используя процедуру для вычисления степени числа, найти значение выражения: y=a4x4 + a3x3 + a2x2 + a1x + a0

program ex2;

var a: array[0..4] of integer;

i, x: integer;

y,s: longint;

Procedure Degree(xx,n: integer; var st: longint);

var i: integer;

begin

st:=1;

for i:=1 to n do st:=st*xx;

end;

{ начало основной программы}

begin

write(‘введите значение переменной х ‘); readln(x);

writeln(‘введите массив коэффициентов’);

for i:=0 to 4 do begin write(‘a[‘,i,’]=’); readln(a[i]); end;

y:=a[0];

for i:=1 to 4 do

begin

Degree(x,i,s); y:=y+a[i]*s;

end;

writeln(‘y=’,y);

end.

Пример 3. Просуммировать различные части массива.

Program sumir;

var a: array [1..100] of integer; sa1, sa2,sa3: integer;

n,l,t: integer;

procedure summa(a:array [1..100] of integer; k,m:integer; var s:integer);

var i:integer;

begin

s:=0;

for i:=k to m do s:=s+a[i];

end;

BEGIN

for t:=1 to 100 do

begin

write(‘введите очередной элемент массива ‘);

readln(a[i]);

end;

summa(a,10,20,sa1);

summa(a, n, l, sa2);

summa(a, n,n+3,sa3);

end.

Задачи:

10.17 Составить программу, в результате которой величина А меняется значением с величиной В, а величина С - с величиной D. (Определить процедуру, осуществляющую обмен значениями двух переменных величин)

10.18 Даны стороны двух треугольников. Найти сумму их периметров и сумму их площадей. (Определить процедуру для расчета периметра и площади треугольника по его сторонам.)

10.19 Даны основания и высоты двух равнобедренных трапеций. Найти сумму их периметров и сумму их площадей (Определить процедуру для расчета периметра и площади равнобедренной трапеции по ее основаниям и высоте)

10.20 Написать рекурсивную процедуру для вывода на экран цифр натурального числа в обратном порядке.

10.21 Написать рекурсивную процедуру для ввода с клавиатуры последовательности чисел и вывода ее на экран в обратном порядке (окончание последовательности - при вводе нуля).

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

Функции

Заголовок функции состоит из слова Function, за которым указывается имя функции, затем в круглых скобках записывается список формальных параметров, далее ставится двоеточие и указывается тип результата функции.

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

Таким образом, общий вид описания функции следующий:

Function Имя[(список формальных параметров)]:Тип результата

описательная часть

Begin

тело функции, в которой обязательно должно быть

присваивание Имя_функции:=значение

End;

Пример 1 Составить программу, подсчитывающую число сочетаний без повторения из n элементов по k. Число сочетания без повторения вычисляется по формуле

Обозначим через n и k переменные для хранения введенных чисел; С - переменную для хранения результата.

Воспользуемся функцией для вычисления факториала числа n. (n!=1*2*..*n)

program sochet;

var n,k: integer;

a1,a2,a3,c: lohgint;

Function factorial(n:integer):longint;

var i: integer;

rez: longint;

begin

rez:=1;

for i:=1 to n do rez:=rez*i;

factorial:=rez;

end;

begin

writeln(‘ ввод n и k:’); readln(n,k);

a1:=factorial(n); { вычисление n!}

a2:=factorial(k); { вычисление k!}

a3:=factorial(n-k); {вычисление (n-k)!}

c:=a1 div (a2*a3); { результат}

writeln(‘результат=’,c);

end.

Первая строка в описании функции - это ее заголовок. Служебное слово Function (функция) указывает на то, что именем factorial названа функция. В скобках записан список формальных параметров функции, состоящий из одной переменной целого типа. Далее в заголовке указан тип значения функции. В данном примере результат функции factorial - длинное целое число.

За заголовком функции следует описательная часть функции, которая, как у программы, может состоять из разделов описания переменных, констант, типов. В данном примере есть переменные i (счетчик цикла) rez (для накопления значения факториала).

Далее идет раздел операторов (тело функции).

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

Пусть n=5, k=3. Когда в программе встречается оператор a1:=factorial(n), выполняются следующие действия:

· выделяется память для переменных, описанных в функции factorial;

· формальному параметру присваивается значение фактического: n:=n (n=5);

· выполняется функция, вычисляется факториал числа 5;

· значение функции передается в место обращения к этой функции, то есть присваивается переменной a1;

· в операторах a2:=factorial(k) a3:=factorial(n-k) еще дважды вызывается функция factorial с параметрами k=3 n-k=2.

Функция - это самостоятельная часть программы, имеющая собственные переменные, которым отводится отдельное место в памяти ЭВМ. Этим объясняется тот факт, что переменные с одинаковыми именами, используемые в функции и в основной программе, являются разными (переменная n основной программы и параметр n функции). При выполнении программы машина «не путает» имена этих переменных, т.к. области их действия не совпадают.

Пример 2: Написать функцию, подсчитывающую количество цифр натурального числа. Используя ее, определить, в каком из двух данных чисел больше цифр.

Program chisla;

Var n1, n2: longint;

k1, k2: byte;

Function kol(x: longint): byte;

var k: byte;

begin

k:=0;

While x<>0 do

begin

Inc(k);

x:=x div 10;

end;

kol:=k;

end;

BEGIN

writeln(‘Введите два числа’); readln(n1, n2);

k1:=kol(n1);

k2:=kol(n2);

if k1=k2 Then writeln(‘одинаковое количество цифр’)

else if k1>k2 Then Writeln(‘в первом числе цифр больше’)

else writeln(‘во втором числе цифр больше’)

END.

Задачи:

10.1 Рассчитать значение х, определив и использовав функцию:

  а)     г)  
б)   д)
в) е)

10.2 Определить значение

а) z=max(a,2b)*max(2a-b,b) б) z=min(a,3b)*min(2a-b,b)

где max(x,y), min(x,y) - максимум и минимум из чисел x,y

При решении:1) не использовать функцию max, min.

2) определить и использовать функцию max,min.

10.3 Даны основания и высоты двух равнобедренных трапеций. Найти сумму их периметров. (Определить функцию для расчета периметра равнобедренной трапеции по ее основаниям м высоте.)

10.4 Даны три квадратных уравнения ax2 + bx + c = 0, bx2 + ax + c = 0, cx2 + ax + + b = 0. Сколько из них имеют вещественные корни? (Определить функцию, позволяющую распознавать наличие вещественных корней в квадратном уравнении.)

10.5 Найти периметр треугольника, заданного координатами своих вершин. (Определить функцию для расчета отрезка по координатам его вершин)

10.6 Даны вещественные числа a, b, c, d, e, f, g.

Найти площадь пятиугольника, изображенного на рисунке. (Определить функцию для расчета площади треугольника по трем сторонам.) е g d   a f b с  

10.7 Даны вещественные числа x1, y1, x2, y2,... x5, y5.Найти площадь пятиугольника (см 10.6) вершины которого имеют координаты (x1, y1), (x2, y2),...(x5, y5). (Определить функцию для расчета площади треугольника по координатам его вершин).

10.8 Даны две последовательности целых чисел: а1, а2,... а8, и b1, b2,... b8. Найти количество четных чисел в первой из них и количество нечетных вол второй. (Определить функцию, позволяющую распознавать четные числа.)

10.9 Найти значение выражения (2*5! + 3*8!)/(6! + 4!), где n! функция.

10.10 Даны два натуральных числа. Выяснить, в каком из них сумма цифр больше.(сумма цифр - функция).

10.11 Даны n различных чисел. Определить максимальное из них. (Определить функцию, находящую максимум из двух различных чисел.)

10.12 Найти НОД(a,b,c)=НОД(НОД(a,b),c). (где НОД(a,b) - функция.)

10.13 Даны n натуральных чисел. Найти их НОД. (где НОД(a,b) - функция.)

10.14 Написать рекурсивную функцию:

а) вычисления суммы цифр натурального числа;

б) вычисления количества цифр натурального числа.

10.15 Даны первый член и разность арифметической прогрессии. Написать рекурсивную функцию для нахождения:

а) n-го члена прогрессии; б) суммы n первых членов прогрессии.

10.16 Даны первый член и знаменатель геометрической прогрессии. Написать рекурсивную функцию для нахождения:

а) n-го члена прогрессии;б) суммы n первых членов прогрессии.

Построение графиков функций и диаграмм.

Для начала работы, немного упростим задачу. А именно, договоримся, что функция задана явно, то есть все наши функции имеют следующий вид y = f(x). И пока мы будем брать только такие функции которые не имеют точек разрыва в исследуемой области определения. Грубо говоря, на рассматриваемой области не должен вычисляться корень из отрицательного числа и не должно выполняться деление на ноль.

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

Для все Х от ЛГ до ПГ делать

Вычислить y=f(x)

Построить точку с координатами (x,y)

Для реальной задачи этот алгоритм работать не будет, по следующим причинам:

1. Он не учитывает, то, как устроена система координат компьютерного монитора. (Начало координат в левом верхнем углу и y растет вниз).

2. Он не учитывает, что экран монитора имеет ограниченные размеры и если значения функции будут слишком велики или слишком велика будет область, на которой требуется график, то значительной части графика мы просто не увидим.

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

Попробуем учесть указанные моменты.

Все эти проблемы можно решить одним махом, если функцию нарисовать в том же масштабе, что и экран монитора. Это очень просто. Пусть, мы желаем просмотреть картинку которая очень мала, например она может быть нарисована в прямоугольнике который в 1000 раз меньше экрана монитора, тогда её перед тем как выводить необходимо увеличить в 1000 раз. Если же она наоборот в 1000 раз больше, то перед выводом её надо в 1000 раз уменьшить.

Выше описано преобразование подобия, но это преобразование ещё не полностью описывает положение картинки на экране. Мало, чтобы картинка совпадала с экраном монитора размерами, ещё необходимо, чтобы совпадали координаты.

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

И последнее, что нужно сделать – это учесть особенное расположение начала системы координат на экране монитора компьютера. Для этого изображение необходимо перевернуть, тогда на экране оно останется прежним.

Итак, мы изложили все, что необходимо на языке геометрических преобразований, но так как язык программирования не умеет работать с понятиями геометрии, и ему необходимы алгебраические выражения, то далее мы рассмотрим каким образом всё вышесказанное записать на языке алгебры.

Введём обозначения:

Left – левая граница исходной области.

Right – правая граница исходной области.

Down – нижняя граница исходной области.

Up – верхняя граница исходной области.

Размеры экрана монитора величина фиксированная. Но для общности примем для них буквенные обозначения:

Long_x – размер по горизонтали

Long_y – размер по вертикали

x, y – значения до выполнения преобразований

x’, y’ – значения после выполнения преобразований

Тогда преобразование подобия запишется следующим образом:

x’ = x/(Right - Left)*Long_x y’ = y/(Up - Down)*Long_y

Преобразование переноса запишем так:

x’’ = x’ – Left y’’ = y’ – Down

И наконец преобразование “отображения сверху вниз” запишется так:

x’’’ = x’’ y’’’ = Long_y – y’’

А сейчас объединим все три преобразования в одно:

Преобразование

1) x’ = x/(Right - Left)*Long_x – Left

2) y’ = Long_y - (y/(Up - Down)*Long_y – Down)

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

Для все точек функции выполнить

Берём очередную точку

Новая точка = Преобразование над очередной точкой

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

Первое. Если взялись строить график, стало быть, нам известна область, на которой мы будем строить график. Эта область конечна и её границы по координате x и есть величины Left, Right.

Предположим, что мы строим график на этой области по N точкам. Это означает, что в нашем распоряжении массив координат y для N точек. Наибольшее значение y в этом массиве есть величина Up и наименьшее значение y есть величина Down.

Тогда Long_x = Right – Left и Long_y = Up – Down.

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

Ввод границ области построения графика.

Ввод количества точек построения.

Расчёт шага построения.

Расчёт значений координат y

Расчёт максимума и минимума значений y – ков

Выполнение операций преобразования.

Выше появился термин “шаг построения”. Разумно строить точки следующим образом. Пусть самая левая точка графика – это левая граница области построения. Следующая точка это левая + шаг построения, то есть небольшое число. И каждая очередная точка это предыдущая + шаг построения. Если делать так, то координаты х можно не держать в массиве. Каждую координата можно рассчитать по очевидной формуле:

xi = Left + шаг * i если первую точку считать с номером 0 и

xi = Left + шаг * (i – 1) если первая точка имеет номер 1.

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

Важное замечание

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

Это означает, что преобразованный график, скорее всего, окажется искаженным, с точностью до подобия или по оси Ox или по оси Oy, но это неизбежная плата за возможность просмотреть весь график.

Построение графика в окрестности точек разрыва

Проблема построения графика в такой окрестности заключается в том, что ордината функции изменяется очень быстро на очень маленьком интервале изменения абсциссы, а вы помните, что наш алгоритм проводит преобразование масштабирования графика функции. Это преобразование в случае обработки окрестности точки разрыва приведёт к тому, что большая часть графика будет изображена в очень маленьком масштабе. Математически это будет верно, но получившаяся картинка окажется совершенно ненаглядной, и построение графика потеряет смысл, так как главная функция графика это всё же наглядность.

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

Как и в случае с экстремумами и точками перегиба нам нельзя пользоваться точными определениями математического анализа, о причинах этого мы уже говорили. Следовательно, первое, что требуется сделать это дать определение разрыва.

Определить разрыв можно так – точка разрыва это такая точка в окрестности, которой функция изменяется слишком быстро.

Это очень неточное определение. Здесь два неясных термина. Во-первых, непонятно, что значит слишком быстро и, во-вторых, какого размера интервал принимается за окрестность точки разрыва. Однако уже ясно, что под это определение может попасть не только точка разрыва, а и такая точка, в окрестности которой функция просто имеет большую первую производную, то есть изменяется действительно быстро, но это наша плата за возможность проведения численного счета. А теперь займёмся уточнением определения.

Мы будем исходить из того, что в окрестности точки разрыва график строится схематично. Это означает, что график строится неточно, а, следовательно, если окрестность будет велика, то и в целом построение графика будет неточным.

Отсюда возникает первая мысль, что размер окрестности должен быть таким, чтобы визуально окрестность точки разрыва не занимала значительную часть области построения графика. Итак нам необходимо уметь искать окрестности точек разрыва.

Для начала заметим, что в окрестности точки разрыва график функции удовлетворяет следующим свойствам:

1. Функция либо неограниченно растёт, либо неограниченно убывает.

2. Скорость её роста увеличивается также неограниченно.

Эти два свойства помогут нам обнаруживать необходимые окрестности с высокой степенью точности. Введём некоторые обозначения.

Max – верхняя граница значений ординат

Min – нижняя граница значений ординат.

Шаг – шаг изменения абсциссы.

А – начало области построения графика

В – конец области построения графика

Важное замечание. Нам важно не просто найти окрестность, а во-первых, достаточно точно определить абсциссу точки разрыва, а во-вторых, определить тип разрыва, а их может быть два:

Нестрогое описание процесса расчётов

Для поиска точек разрыва, мы пройдём всю область построения с шагом достаточно маленьким, но таким который позволит пройти всю область за разумное время. На каждом шаге процесс будет вычисляться новая абсцисса путем прибавления к предыдущей абсциссе величины шага. Для каждой вновь посчитанной абсциссы будем вычислять ординату, и если посчитанная ордината окажется за пределами отрезка [min, max] то будем предполагать, что найдена окрестность точки разрыва, после чего должен быть запущен процесс проверки этого предположения.

Min – это минимальная из уже посчитанных ординат и max – это максимальная из уже посчитанных ординат.

Процесс проверки предположения заключается в следующем:

· Резко уменьшим шаг движения и сделав ещё некоторое количество шагов убедимся, что функция продолжает изменятся быстрым темпом в том же направлении. Если этого не происходит, то, следовательно, это не окрестность точки разрыва.

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

· Будем сжимать окрестность с сохранением её свойств до тех пор, пока она не станет достаточно маленькой. Её центр и есть точка разрыва.


Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: