Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Глава 3_2.doc
Скачиваний:
25
Добавлен:
13.03.2016
Размер:
203.78 Кб
Скачать

Объявление динамических массивов

Динамические массивы объявляются с атрибутом ALLOCATABLE. Каждое измерение обозначается двоеточием (:). Память под динамические массивы выделяется при выполнении программы оператором

allocate (список динамических массивов).

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

deallocate (список динамических массивов)

Пример:

integer n, m

integer, allocatable :: x(:,:)

read*, n, m

allocate (x(n, m))!выделение памяти под массив x(n, m)

………..

deallocate (x) !освобождение памяти, занятой массивом

Сечение массива

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

Сечение массива задается с помощью индексного триплета:

[нижняя граница]:[верхняя граница]:[шаг].

Параметры триплета – целочисленные выражения. Каждый элемент триплета является необязательным.

Например, в программе описан массив:integer X(10). Возможны следующие варианты обозначения сечений этого массива:

X(:5) – первые 5 элементов массива;

X(5:) – элементы массива с 5-го по 10-й;

X(2:7) – элементы массива со 2-го по 7-й;

X(2:10:2) – все четные элементы массива;

X(::2) – все нечетные элементы массива.

Примерами сечения двумерного массива являются его строки и столбцы, например:

real p(4, 10)

p(3, :) = 0 ! 3-я строка матрицы обнуляется

p(:, 5) = 1 ! 5-й столбец матрицы заполняется единицами

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

Пример программы перестановки столбцов матрицы.

program Column

integer,parameter :: m=3, n=3

real, dimension(1:m,1:n) :: a

real vect(m)

real :: pr, s=0.

integer :: i, c1=1, c2=3

a(1,:)=(/1.,2.,3./) !инициализация 1-й строки с

! помощью сечения

a(2,:)=(/(i*2,i=1,3)/)!инициализация 2-й строки,

!встроенный DO-цикл

a(3,:)=(/3.,2.,1./) !инициализация 3-й строки

print *,' перестановка столбцов c1 и c2'

do i=1,n !вывод матрицы с помощью сечения

print *, a(i,:)

end do

vect = a(:,c1) !запоминание столбца c1

!сечение и vect д.б. согласованы

a(:,c1) = a(:,c2) !перестановка столбцов c1и c2

a(:,c2) = vect

print *,'Результат'

do i=1,n

print *,a(i,:)

end do

end program

Оператор WHERE

Оператор WHERE позволяет обращаться одновременно к множеству элементов массива, удовлетворяющих определенному условию. Один оператор WHERE заменяет собой структуру «цикл с вложенным ветвлением».

Например, в программе объявлен массив:

integer :: R(5) = (/ 1, -1, 1, -1, 1 /)

Требуется обнулить все его отрицательные элементы.

Задачу можно решить следующим традиционным способом:

do i = 1, 5

if(R(i) < 0) R(i) = 0

end do

С помощью оператора WHERE задача решается так:

where(R <0) R=0

Смысл следующий: всем элементам массива R, меньшим нуля, присвоить ноль.

Существует также конструкция WHERE-ELSEWHER-ENDWERE. Например, в том же самом массиве требуется занулить отрицательные и удвоить все остальные элементы. Программа будет следующей:

where(R < 0)

R = 0

elsewhere

R=2*R

end where

Типовые задачи обработки массива

Пример 1. Вычисление среднего значения. Дана таблица среднемесячных температур в течение года: T(1:12) – одномерный вещественный массив. Требуется вычислить среднегодовую температуру, а также ежемесячные отклонения от этой величины.

Program Example

Integer, parameter:: N=12

Real T(N), Dt(N), St

Integer i

! Ввод исходных данных

print *,'Вводите таблицу температур'

do i= 1, N

write(*,’(I3,a,\)’) i,’:’

Read *,T(i)

enddo

!Вычисление средней температуры

St = 0;

do i= 1, N

St = St + T[i]

enddo

St=St/N;

!Вычисление таблицы отклонений от среднего

do i= 1, N

Dt(i)= St – T(i)

enddo

!Вывод результатов

print *,' Средняя температура равна ', St

print*, 'Отклонения от средней температуры:'

do i= 1, N

print ‘(I3,A,F6.2)’, i, ':', Dt(i)

enddo

End program Example

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

Пример 2. Выбор максимального элемента. Пусть из рассмотренного выше массива температур требуется отобрать самую высокую температуру и номер месяца, ей соответствующий. Идея алгоритма решения этой задачи: чтобы получить максимальную температуру в вещественной переменной TMax, сначала в нее заносится первое значение массива – элемент T(1). Затем поочередно сравнивается значение TMax с остальными элементами массива температур, и каждое значение, большее, чем TMax, присваивается этой переменной. Для получения номера самого теплого месяца в целой переменной NumMax в нее следует каждый раз засылать номер элемента массива температур одновременно с занесением в TMax его значения.

TMax = T(1)

NumMax = 1

do i= 2, N

If (T(i) > Tmax) Then

TMax = T(i)

NumMax = i

endif

enddo

Заметим, что если в массиве температур несколько значений, равных максимальному, то в NumMax будет получен первый номер из этих элементов. Чтобы получить последнюю дату, нужно в операторе if заменить знак отношения ">" на "> =".

Пример 3. Сортировка массива. В одномерном массиве X из N элементов требуется произвести перестановку значений так, чтобы они расположились по возрастанию, т.е. X1  X2  ... XN.

Существует целый класс алгоритмов сортировки. Ниже описан алгоритм, который называется «метод пузырька».

Идея: производится последовательное упорядочивание смежных пар элементов массива: X1 и X2, X2 и X3,..., XN-1 и XN. В итоге максимальное значение переместится в XN. Затем ту же процедуру повторяют до XN-1 и т.д., вплоть до цепочки из двух элементов X1 и X2. Такой алгоритм будет иметь структуру двух вложенных циклов, причем внутренний цикл – переменной (сокращающейся) длины.

do I=1,N-1

do K = 1,N–I

If (X(K)> X(K+1)then

A=X(K)

X(K)=X(K+1)

X(K+1)=A

Endif

Enddo

enddo

Массивы в процедурах

Массив может быть как аргументом процедуры, так и ее результатом. Рассмотрим пример. Составим процедуру-функцию, вычисляющую евклидову норму вектора. Евклидова норма равна корню квадратному из суммы квадратов элементов вектора.

function Norma(X,L) !параметры: имя и размер массива

real Norma

integer L,i

real X(L) !Описание формального аргумента-массива

Norma=0

Do i=1,L

Norma=Norma+X(i)**2

Enddo

Norma=sqrt(Norma)

End function

Пусть в основной программе присутствует описание:

integer, parameter m=10, n=20

real A(m), B(n), Na, Nb

Далее значения массивов А и В вводятся или вычисляются. Вычисление нормы вектора А будет получено в переменной Na, а норма вектора В в переменной Nb в результате выполнения операторов:

Na=Norma(A,m)

Nb=Norma(B,n)

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

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

integer, parameter :: n = 5, m = 10, k = m*n

real a(m, n) /k*1.0/, b(m, n) /k*2.0/

call swap(a, b, m, n)

write(*, *) b

end

subroutine swap(x, y, p, q)

integer p, q

real x(p*q), y(p*q) ! x и y – вектора размера p*q

real r(size(x)) ! r – автоматический массив

r = x; x = y; y = r ! функция size(x) определяет

!размер массива x

end subroutine swap

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

К автоматическим объектам (массив r в примере) относятся объекты данных, размеры кото­рых зависят от неконстантных описательных выражений и которые не яв­ляются формальными параметрами процедуры.

Встроенные функции для работы с массивами

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

Функция

Действие, выполняемое функцией

SIZE(array[,dim])

- возвращает стандартное целое, равное размеру массива array. Если присутствует целый параметр dim – номер измерения массива, то возвращает его протяженность

MAXLOC(array[,mask][,dim])

Возвращает одномерный массив, размер которого равен рангу массива array. Значения элементов массива-результата равны индексам максимального элемента числового массива array; mask – необязательное условие, которому должно удовлетворять значение необязательного элемента. Если несколько элементов содержат максимальное значение, то берется первый по порядку их следования в array.

MINLOC(array[,mask][,dim])

Выполняет те же действия, что и MAXLOC, но для минимального элемента массива

MAXVAL(array[,dim][,mask])

Возвращает максимальное, удовлетворяющее необязательной маске mask значение числового массива array вдоль заданного необязательного измерения dim.

MINVAL(array[,dim][,mask])

Подобен MAXVAL, но ищет минимальный элемент массива

PRODUCT(array[,dim][,mask])

Вычисляет произведение всех элементов массива вдоль необязательного измерения dim; перемножаемые элементы могут отбираться необязательной маской mask

SUM(array[,dim][,mask])

Подобна PRODUCT, но вычисляет сумму элементов массива

DOT_PRODUCT(vector_a, vector_b)

Вычисляет скалярное произведение двух одномерных массивов (векторов) vector_a, vector_b

MATMUL(matrix_a, matrix_b)

Осуществляет перемножение двух числовых матриц matrix_a, matrix_b

TRANSPOSE(matrix)

Транспонирует матрицу (двумерный массив) matrix

Упражнения

1. Дан вектор {zi}, = 1,...,50. Вычислить длину этого вектора:

2. Вычислить полином 10-й степени по формуле Горнера:

a10x10 + a9x9 + ... + a1x + a0 = ((...(a10x + a9)x + a8)x + ... + a1)x + a0.

3. Для вектора {xi}, = 1,...,20 подсчитать количество компонент, значения которых лежат в интервале [0,1].

4. Даны два вектора{xi}, {yi}, = 1,...,10, упорядоченные по возрастанию. Слить их в один вектор {zi}, i = 1,...,20 так, чтобы сохранилась упорядоченность.

5. Дан массив, состоящий из 100 целых чисел:

а) вывести все числа, которые встречаются в этом массиве несколько раз;

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

6. В целочисленной матрице размером 10  10 найти значение и индексы максимального элемента. Составить два варианта программы: без использования стандартной функции и с использованием стандартной функции.

7. В двоичной матрице 5  10 определить номер строки с наибольшим количеством нулей.

8. Все строки вещественной матрицы 10  15 упорядочить по убыванию значений их элементов.

9. Транспонировать целочисленную матрицу 5  5, т.е. перевернуть вокруг главной диагонали. Составить два варианта программы: без использования стандартной функции и с использованием стандартной функции.

10. В двоичной матрице 10  10 найти совпадающие строки.

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

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

96