Для компактности изображения массива на экране в каждой строке экрана целесообразно печатать несколько элементов массива.
Пусть формат вывода элемента массива имеет вид 8:2. Устанавливая между числами два пробела, в одной строке экрана можно разместить 8 чисел (строка экрана содержит 80 позиций). Тогда программа вывода может иметь вид:
ConstNmax = 500;
TypeAr = array[1..Nmax] of real;
Vark : byte;
i,n : word;
X : Ar;
Begin
.....................
k:=0;
Fori:=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 thenWriteln;
Переменная k - это счетчик количества чисел, выводимых в одну строку экрана. Пока k < 8, работает процедура Write, размещая очередные элементы массива в одной и той же строке экрана. При k = 8 после вывода числа производится переход на следующую строку экрана, при этом счетчику k присваивается нулевое значение.
Предположим, что в массиве X количество элементов не кратно 8. Тогда вывод последнего элемента будет осуществлен процедурой Write, следовательно, не будет произведен переход на новую строку экрана. Если в программе после вывода массива X выполняется еще вывод хотя бы одного числа, то это число будет размещено в той же строке экрана, где расположен элемент , что по крайней мере неэстетично. Для предотвращения такой ситуации в вышеприведенной программе записан оператор "Ifk > 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;
Vari, { параметр цикла }
n : word; { кол-во элементов массива }
S : real; { среднее арифметическое значение }
X : Ar; { исходный массив }
Begin
Ввод и печать n, X
S:=0;
For i:=1 ton do
S:=S+x[i];
S:=S/n;
Печать S
End.
При старте программы выделяется память для всех переменных, описанных в разделе Var, т.е. каждому имени переменной ставится в соответствие адрес конкретного поля памяти. Эти поля памяти, как правило, не обнуляются, они могут быть заполнены случайными последовательностями битов. Поэтому в программе MiddleAr перед накоплением в переменной S суммы элементов массива X производится обнуление этой переменной оператором S := 0 .
Следует обратить внимание еще на одно обстоятельство. Массиву Х в программе выделяется память, необходимая для размещения 500 элементов. В принципе в программе можно было бы написать:
For i:=1 toNmax do
S:=S+x[i];
S:=S/Nmax;
Однако это означало бы, что программа может обрабатывать лишь массив, содержащий 500 элементов, но не 499 или 100. Поэтому для обеспечения универсальности работы программы обработке подвергается текущее количество элементов n в предположении, что .
Пример 2. Вычислить среднее арифметическое значение положительных элементов массива .
Program MiddleAr;
Const Nmax = 500;
Type Ar = array[1..Nmax] of real;
Vari, { параметр цикла }
k, { кол-во положительных элементов массива }
n : word; { общее кол-во элементов массива }
S : real; { среднее арифметическое значение }
X : Ar; { исходный массив }
Begin
Ввод и печать n, X
S:=0; k:=0;
For i:=1 ton do
Ifx[i]>0 then
Begin
S:=S+x[i]; Inc(k)
End;
Ifk>0 then{ блокировка деления на нуль }
S:=S/n;
Печать S
End.
В частном случае в массиве X может не быть ни одного положительного элемента (k=0). Тогда при отсутствии оператора «Ifx[i]>0 then»было бы прерывание программы с сообщением «Zero divide» («Деление на нуль»).
Пример 3.Определить .
Program MaxElem;
Const Nmax = 500;
Type Ar = array[1..Nmax] of integer;
Vari, n : word;
Xmax : integer;
X : Ar;
Begin
Ввод и печать n,X
Xmax:=x[1];
Fori:=2 to n do
Ifx[i]>Xmax then
Xmax:=x[i];
Печать Xmax
End.
Пример 4.Обменять местами максимальный и минимальный элементы массива X.
Здесь требуется найти не только значения переменных Xmax и Xmin, но и положение (индексы) соответствующих им элементов в массиве X (значения переменных imax и imin).
Вариант 1.
Program Exchange;
Const Nmax = 500;
TypeAr = 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;
Fori:=2 ton do
Begin
Ifx[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 ton do
Ifx[i]>Xmax then
Begin
Xmax:=x[i]; imax:=i
End
Else
Ifx[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.
ProgramNegElem;
Const Nmax = 500;
TypeAr = array[1..Nmax] of integer;
Vari,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.
Вариант 2 (фрагмент).
ineg:=0; i:=1;
While (i<=n) and (ineg=0) do
Ifx[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.
ProgramPosElem;
Const Nmax = 500;
Type Ar = array[1..Nmax] of integer;
Vari,n,ipos : word;
X : Ar;
Begin
Ввод и печать n,X
ipos:=0;
For i:=1 ton do
Ifx[i]>0 then
ipos:=i;
Writeln('ipos= ',ipos);
End.
В программе просматриваются все элементы массива X, что нерационально с точки зрения затрат машинного времени. Более эффективной является программа варианта 2, в которой просмотр массива X осуществляется справа налево до обнаружения ближайшего положительного элемента.
Вариант 2 (фрагмент).
ipos:=0;
For i:=n downto1 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;
ConstNmax = 400;
TypeKoef = array[0..Nmax] of real;
Vari,n : integer;
P,x : real;
A : Koef;
Begin
Ввод и печать n,A,x
P := a[n];
Fori:=n-1 downto 0 do
P:=P*x+a[i];
Печать P
End.
Конкретную запись полинома, заданного в виде явного выражения, также рекомендуется вычислять по схеме Горнера. Например, полином
по схеме Горнера имеет вид:
.
Пример 8. Расположить элементы массива в обратном порядке.
При выполнении заданного преобразования нужно произвести обмен значений элементов и , и , и и так далее до достижения "середины" массива .
Вариант 1.
Program BackOrder;
ConstNmax = 500;
TypeAr = array[1..Nmax] of real;
Var i,n : integer;
R : real;
X : Ar;
Begin
Ввод и печать n, X
Fori:=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, остальная часть программы не изменяется.