Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Turbo Pascal / Stud_1_1 / LecRus / MainPart.doc
Скачиваний:
117
Добавлен:
03.03.2016
Размер:
5.03 Mб
Скачать

3. Вывод одномерного массива на экран.

Для компактности изображения массива на экране в каждой строке экрана целесообразно печатать несколько элементов массива.

Пусть формат вывода элемента массива имеет вид 8:2. Устанавливая между числами два пробела, в одной строке экрана можно разместить 8 чисел (строка экрана содержит 80 позиций). Тогда программа вывода может иметь вид:

Const Nmax = 500;

Type Ar = array[1..Nmax] of real;

Var k : byte;

i,n : word;

X : Ar;

Begin

.....................

k:=0;

For i:=1 to n do

Begin

k:=k+1;

If k<8 then

Write(x[i]:8:2,' ')

Else

Begin

k:=0; Writeln(x[i]:8:2);

End;

End;

If k>0 then Writeln;

Переменная k - это счетчик количества чисел, выводимых в одну строку экрана. Пока k < 8, работает процедура Write, размещая очередные элементы массива в одной и той же строке экрана. При k = 8 после вывода числа производится переход на следующую строку экрана, при этом счетчику k присваивается нулевое значение.

Предположим, что в массиве X количество элементов не кратно 8. Тогда вывод последнего элемента будет осуществлен процедурой Write, следовательно, не будет произведен переход на новую строку экрана. Если в программе после вывода массива X выполняется еще вывод хотя бы одного числа, то это число будет размещено в той же строке экрана, где расположен элемент , что по крайней мере неэстетично. Для предотвращения такой ситуации в вышеприведенной программе записан оператор "If k > 0 then Writeln".

В дальнейшем для увеличения и уменьшения значения целой переменной будем использовать процедуры Inc и Dec (инкремент и декремент), создающие эффективные машинные коды.

Inc(k) эквивалентно k:=k+1;

Inc(k,m) эквивалентно k:=k+m;

Dec(k) эквивалентно k:=k-1;

Dec(k,m) эквивалентно k:=k-m.

В частности, Inc(k) работает примерно на 30 % быстрее, чем k := k+1.

Примеры обработки одномерных массивов

Пример 1. Вычислить среднее арифметическое значение элементов массива .

Program MiddleAr;

Const Nmax = 500;

Type Ar = array[1..Nmax] of real;

Var i, { параметр цикла }

n : word; { кол-во элементов массива }

S : real; { среднее арифметическое значение }

X : Ar; { исходный массив }

Begin

Ввод и печать n, X

S:=0;

For i:=1 to n do

S:=S+x[i];

S:=S/n;

Печать S

End.

При старте программы выделяется память для всех переменных, описанных в разделе Var, т.е. каждому имени переменной ставится в соответствие адрес конкретного поля памяти. Эти поля памяти, как правило, не обнуляются, они могут быть заполнены случайными последовательностями битов. Поэтому в программе MiddleAr перед накоплением в переменной S суммы элементов массива X производится обнуление этой переменной оператором S := 0 .

Следует обратить внимание еще на одно обстоятельство. Массиву Х в программе выделяется память, необходимая для размещения 500 элементов. В принципе в программе можно было бы написать:

For i:=1 to Nmax do

S:=S+x[i];

S:=S/Nmax;

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

Пример 2. Вычислить среднее арифметическое значение положительных элементов массива .

Program MiddlePos;

Const Nmax = 500;

Type Ar = array[1..Nmax] of real;

Var i, { параметр цикла }

k, { кол-во положительных элементов массива }

n : word; { общее кол-во элементов массива }

S : real; { среднее арифметическое значение }

X : Ar; { исходный массив }

Begin

Ввод и печать n, X

S:=0; k:=0;

For i:=1 to n do

If x[i]>0 then

Begin

S:=S+x[i]; Inc(k)

End;

If k>0 then { блокировка деления на нуль }

S:=S/n;

Печать S

End.

В частном случае в массиве X может не быть ни одного положительного элемента (k=0). Тогда при отсутствии оператора «If x[i]>0 then» было бы прерывание программы с сообщением «Zero divide» («Деление на нуль»).

Пример 3. Определить .

Program MaxElem;

Const Nmax = 500;

Type Ar = array[1..Nmax] of integer;

Var i, n : word;

Xmax : integer;

X : Ar;

Begin

Ввод и печать n,X

Xmax:=x[1];

For i:=2 to n do

If x[i]>Xmax then

Xmax:=x[i];

Печать Xmax

End.

Пример 4. Обменять местами максимальный и минимальный элементы массива X.

Здесь требуется найти не только значения переменных Xmax и Xmin, но и положение (индексы) соответствующих им элементов в массиве X (значения переменных imax и imin).

Вариант 1.

Program Exchange;

Const Nmax = 500;

Type Ar = array[1..Nmax] of integer;

Var i,n,imax,imin : word;

Xmax,Xmin : integer;

X : Ar;

Begin

Ввод и печать n,X

Xmax:=x[1]; Xmin:=x[1];

imax:=1; imin:=1;

For i:=2 to n do

Begin

If x[i]>Xmax then

Begin

Xmax:=x[i]; imax:=i

End;

If x[i]<Xmin then

Begin

Xmin:=x[i]; imin:=i

End;

End;

x[imax]:=Xmin; x[imin]:=Xmax;

Печать X

End.

В каждом цикле элемент сравнивается со значениями переменных Xmax и Xmin. В то же время очевидно, что если выполняется условие > Xmax, то проверка отношения < Xmin является излишней. Указанное замечание учтено в варианте 2.

Вариант 2 (фрагмент).

For i:=2 to n do

If x[i]>Xmax then

Begin

Xmax:=x[i]; imax:=i

End

Else

If x[i]<Xmin then

Begin

Xmin:=x[i]; imin:=i

End;

При обмене значений элементов x[imax] и x[imin] использовано то обстоятельство, что после окончания обработки массива известны не только значения индексов imax и imin, но и численные значения переменных Xmax и Xmin. Обмен в данном случае осуществляется по такой схеме:

Примечание. Было бы совершенно неправильно выполнять обмен максимального и минимального элементов массива X операторами

R := Xmax; Xmax := Xmin; Xmin:= R;

(R - переменная типа real), так как здесь обмениваются значения переменных Xmax и Xmin, а не значения элементов массива X с индексами imax и imin.

Пример 5. В массиве X найти значение и положение первого отрицательного элемента.

Решение рассматриваемой задачи выполнено в двух вариантах.

Вариант 1.

Program NegElem;

Const Nmax = 500;

Type Ar = array[1..Nmax] of integer;

Var i,n,ineg : word;

Xneg : integer;

X : Ar;

Begin

Ввод и печать n,X

ineg:=0;

For i:=1 to n do

If x[i]<0 then

Begin

Xneg:=x[i]; ineg:=i;

Break

End;

Writeln('ineg= ',ineg);

If ineg>0 then

Writeln('Xneg= ',Xneg);

End.

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

Если в массиве X нет ни одного отрицательного элемента, в программе будет отпечатано ineg = 0, в противном случае - конкретные значения ineg, Xneg.

Примечание. Процедура Break эквивалентна оператору Goto Met, где Met – метка после окончания цикла For.

Вариант 2 (фрагмент).

ineg:=0; i:=1;

While (i<=n) and (ineg=0) do

If x[i]<0 then

Begin

Xneg:=x[i]; ineg:=i;

End

Else

Inc(i);

Writeln('ineg= ',ineg);

If ineg>0 then

Writeln('Xneg= ',Xneg:12);

Вариант 1 работает примерно в 2 раза быстрее (отсутствие проверки ineg = 0 в каждом цикле).

Пример 6. В массиве X определить местоположение последнего положительного элемента.

Вариант 1.

Program PosElem;

Const Nmax = 500;

Type Ar = array[1..Nmax] of integer;

Var i,n,ipos : word;

X : Ar;

Begin

Ввод и печать n,X

ipos:=0;

For i:=1 to n do

If x[i]>0 then

ipos:=i;

Writeln('ipos= ',ipos);

End.

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

Вариант 2 (фрагмент).

ipos:=0;

For i:=n downto 1 do

If x[i]>0 then

Begin

ipos:=i; Break

End;

Writeln('ipos= ',ipos);

Пример 7. Вычисление значения полинома.

Полином (многочлен)

целесообразно всегда вычислять по схеме Горнера:

.

Схема Горнера обладает следующими преимуществами по сравнению с обычной записью полинома:

- меньшее количество операций умножения;

- меньшая погрешность вычислений;

- удобство реализации вычислений в виде цикла.

Для вычисления полинома по обычной схеме требуется операций умножения, по схеме Горнера - таких операций.

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

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

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

Вычисления в программе организуются по следующей методике:

P := a[n]

P := P * x + a[n-1]

P := P * x + a[n-2]

...................

P := P * x + a[1]

P := P * x + a[0]

Program Gorner;

Const Nmax = 400;

Type Koef = array[0..Nmax] of real;

Var i,n : integer;

P,x : real;

A : Koef;

Begin

Ввод и печать n,A,x

P := a[n];

For i:=n-1 downto 0 do

P:=P*x+a[i];

Печать P

End.

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

по схеме Горнера имеет вид:

.

Пример 8. Расположить элементы массива в обратном порядке.

При выполнении заданного преобразования нужно произвести обмен значений элементов и , и , и и так далее до достижения "середины" массива .

Вариант 1.

Program BackOrder;

Const Nmax = 500;

Type Ar = array[1..Nmax] of real;

Var i,n : integer;

R : real;

X : Ar;

Begin

Ввод и печать n, X

For i:=1 to n div 2 do

Begin

R:=x[i]; x[i]:=x[n-i+1]; x[n-i+1]:=R

End;

Печать массива X

End.

Вариант 2 (фрагмент).

i:=1; j:=n;

While i<j do

Begin

R:=x[i]; x[i]:=x[j]; x[j]:=R;

Inc(i); Dec(j);

End;

Оба варианта примера 8 равнозначны с точки зрения эффективности вычислений, но вариант 2 более нагляден. Второй вариант более удобен также в случае, когда требуется выполнить перестановку не всего массива, а подмассива, например, с номера n1 до номера n2. Тогда перед циклом записываются операторы i:=n1 и j:=n2, остальная часть программы не изменяется.

Вариант 3. Использование буферного массива.

Program BackOrder3;

Const Nmax = 500;

Type Ar = array[1..Nmax] of real;

Var i,n : integer;

X,Y : Ar;

Begin

Ввод и печать n, X

For i:=1 to n do

y[n-i+1]:=x[i];

X:=Y;

Печать массива X

End.

Оператор X:=Y в варианте 3 допустим, поскольку массивы X иY описаны одним и тем же именем типа. При этом производится пересылка всего поля Y в поле X, т.е. Nmax элементов в соответствии с объявлением типа данного массива.

Недостаток варианта 3 вполне очевиден – это использование буферного массива.

О Г Р А Н И Ч Е Н И Я В И С П О Л Ь З О В А Н И И

О П Е Р А Т О Р А F O R

Ограничения в использовании оператора цикла с параметром естественным образом вытекают из приведенного ранее описания этого оператора. Рассмотрим еще раз по пунктам описание оператора For и вытекающие из этого следствия.

Соседние файлы в папке LecRus