Массивы
Массивы имеются во всех языках программирования. Однако в каждом языке
собственные подходы в работе с массивами. Одномерный массив соответствует
вектору в математике, и его элементы располагаются в последовательных ячейках памяти
ПК. Одномерные массивы сопоставимы в разных языках. Однако, например, матрица
представляется
- в C как массив указателей
- в Паскале как массив
массивов
- в Фортране как
прямоугольная таблица
Многомерные массивы с dim>1, тем более с dim>2, а особенно с переменными
размерностями, и в C и Паскале непременно вызовут затруднения, тогда как в
Фортране все массивы описываются и обрабатываются единообразно.
Более точно, в Фортране
массив - это прямоугольная таблица с числом измерений от dim=0 до dim=7,
таблица состоит из однотипных элементов, объединенных общим именем.
Важнейшие частные случаи:
- dim=0 – скаляр -
переменная, мы ее уже использовали, объявляя ее тип в списке integer
real complex logical character , можно type (имя_рек_типа) список
- dim=1 – вектор или
одномерный массив
- 7³dim>1 - многомерный массив
- dim=2 – матрица, таблица
или двумерный массив
- dim=3 – система таблиц или
трехмерный массив
Понятиям многомерная величина матрица, вектор, скаляр из математики в
Фортране соответствуют массивы различной размерности. Элементы массива доступны
по индексам, число которых соответствует числу измерений массива. В частности,
переменная и константа - это массивы с числом измерений dim=0, то есть без
индексов. Элемент массива называют переменной с индексами в отличие от ранее использовавшейся
переменной без индексов, называемой также простой переменной. Проиллюстрируем
пользу массивов.
Пример 1. Подсчитать для 60 вводимых чисел s-среднее и
среднеквадратическое отклонение
Попробуем разобраться, сравнив 3 варианта решения задачи, см. колонки 1..3 в
таблице.
до
Fortran-90
|
в
стиле Fortran-90
|
1 - простая переменная x
|
2 - массив X покомпонентно
|
3 - X - вектор
|
Скаляр
обозначили маленькой букой x, вектор X - большой буквой, но Фортран
различает их не по этому признаку
|
Program x_scalar
Real sum,s,Sigma,
Integer k
Sum = 0 !
среднее
do k = 1,60
Read(1,*) x ! x забываем
Write(*,*) ‘x=’, x
Sum = sum +x
End do ! ..k = 1,60 !
s = sum / 60.
Write(*,*) 'среднее =', s
! среднеквадр. отклонение
Rewind ( 1 ) ! к началу файла
Do k = 1,60 ! x не хранятся
Read(1,*) x ! вводят снова
Sum = sum +(s-x)**2
End do
Sigma = sqrt( sum ) / 60.
Write(*,*) 'ско =', sigma
End
|
Program X_component
Real sum,s,Sigma, X (60)
Integer :: k
Read(1,*) x ! читаем все
Write(*, "(10f5.2)" ) X
Sum = 0 !
среднее
do k = 1,60
Sum = sum +X(k)
end do ! хранят все Xk
s = sum / 60
Write(*,*) 'среднее =', s
! среднеквадр. отклонение
do k = 1,60 ! все X хранятся
sum = sum +(s-X(k))**2
end do ! ..k = 1,60
Sigma = sqrt( sum ) / 60
write(*,*) 'ско =', sigma
End
|
Program X_vector
Integer,parameter :: N=60
Real, dimension(1: N) :: X
Real s
! читаем и печатаем вектор X
Read(1,*) X ; Write(*,
"(10f5.2)" ) X
S = sum(X)/N;
write(*,*) 'среднее =', s
Write(*,*) 'ско =', sqrt(sum((X-s)**2))/
N
End
|
Пример
того, как не имеет смысла писать.
|
Проще
- нет повторного чтения. В циклах компоненты вектора вместо простой
переменной.
|
Радикальное
упрощение, в параметрах функции суммирования векторы вместо компонент.
|
До появления
Fortran-90 у
программиста была возможность манипулировать с простыми переменными, см.
колонку 1, а также с переменными с индексами, см. колонку 2 в таблице. В
Fortran-90 появилась возможность манипулировать с векторами и матрицами, см.
колонку 3 в таблице. Обратите внимание, насколько лаконична и понятна программа
в стиле Fortran-90: прочитать - вычислить - напечатать. В ней
просматривается общая тенденция - перенести центр тяжести на раздел описаний и
формулы, избавив программу от технических деталей, - в данном примере стали
ненужными циклы.
Для того, чтобы это
обеспечить в Fortran-90 появились
- Емкие лаконичные средства описания
атрибутов (свойств) объектов
- Мощные и компактные средства конструирования
массивов и сечений массивов (нечто похожее на минор матрицы)
- Множество стандартных элементных
функций, одинаково применимых и к переменным, и к векторам, и к матрицам
- Пакет функций для измерения и
препарирования массивов
- Ряд новых функций для работы с векторами
и матрицами
Новый принцип описания объектов в Фортране-90
Новый принцип описания объектов совмещает
полное объявление типа и размерности, а также всех прочих атрибутов массива.
Важно, что все собрано в одном описании. Если несколько массивов имеют
одинаковый набор свойств, то они идут одним списком. Именно такой способ
рекомендован как основной в обновленном языке Фортран-90, изобилующем многими
уточняющими атрибутами. Например, вполне понятно описание в стиле Фортран-90
Integer*1, dimension (1:5), parameter :: CHET=(/
0,2,4,6,8 /), NECHET=(/ 1,3,5,7,9 /)
в этом описании имеется
- знак двойного двоеточия
"::" в середине строки говорит о том, что по
определению набор атрибутов (свойств), перечисленных слева
от "::", относится ко всем объектам,
указанным справа от "::"
- в примере справа от "::"
два вектора CHET, NECHET, что свидетельствует о совпадении их свойств,
при разных значениях
- атрибут integer*1, нужен,
чтобы указать целый тип элементов, компактно упакованных, каждый в 1 байт
- атрибут dimension,
чтобы отличить массив от простой переменной и дать размерностные характеристики
массива
- атрибут parameter,
чтобы указать, что всё это константы
- составной знак (/ .. ..
/) - это конструктор массива, в данном примере целые числа из
диапазона 0:9 подразделены на четные CHET и нечетные NECHET
В Фортране-90 атрибут dimension может иметь не только массив, но и
функция.
В Фортране-77 Real и dimension
являются не атрибутами, а операторами, допускается совмещать описания dimension
X(60) и Real X, опуская dimension. Такой “экономный” способ
описания не вполне согласуется с требованием явного полного перечисления
свойств объектов, он не стал основным в Фортране-90
В Фортране-77 допускается писать одно
описание
|
Вместо двух описаний
|
Real X(60)
|
Real X
dimension X(60)
|
MS в опережение
стандарта также разрешила применение некоторых атрибутов, которые по их
предложению в MS Ф5.1 записывались в квадратных скобках после имени объекта,
например, Real Matrix [allocatable](:,:) Написание атрибутов в квадратных скобках не
принято в Фортране-90.
Характеристики массива
Одномерный, двумерный, трехмерный, любой многомерный массив описываются
единообразно
- одномерный массив
real X(60) - это вектор из 60 однотипных элементов
- двумерный массив real
T(3,5) - это матрица однотипных элементов из 3 строк и 5 столбцов
- трехмерный массив real
Edr(4,3,2) -
это система из 2 матриц, каждая по 4 строки и 3 столбца
В качестве индексов для выбора элементов массива вместо безликих
математических обозначений i,j,k лучше использовать "говорящие" имена
вроде str,
stl, tbl
·
integer str ! номер строки
·
integer stl ! номер столбца
·
integer tbl ! номер таблицы
"Говорящие" имена str, stl,
tbl сложнее перепутать местами между собой, зная, что именно в этом порядке
должны перечисляться индексы трехмерного массива Radius( str, stl, tbl ) или Radius(3,2,3) – элемент
3-ей строки, 2-ого столбца, 3-ей таблицы. Элемент двумерного массива можно выбрать, задавая 2 индекса
Dlina(2,5) или Dlina(str,stl).
Иллюстрируем характеристики массива на примере трех массивов
real*8,allocatable,dimension(-2:2,:) :: Dlina
integer*2, save, dimension(1:5,3,1:3) :: Radius
real*4, dimension(1:5,2:4,11:13) :: Ploschad
Характеристики, объявляемые в описании массива
- имя
массива пишется по обычным правилам, лучше по смыслу задачи – обязательная
характеристика
в нашем примере имена массивов Dlina, Radius, Ploschad
- тип массива – желательная
характеристика, (implicit None отменит необязательность
в описании типа)
тип массива (как и для простой переменной) определяет как каждый элемент
массива хранится в памяти ПК, сколько байтов занимает, какие к нему
применимы операции; имеется 5 базовых типов (integer real complex
logical character ) плюс любое количество производных типов данных,
описываемых в составных операторах
type Имя_типа .. .. end
Type Имя_типа
в нашем примере тип real для массива Dlina и integer*2 для массива Radius
- ранг массива или
число измерений – обязательная, неявная характеристика
допускается ранг от 1 до 7
в нашем примере для массива Dlina ранг, то есть число измерений 2, так как
после dimension в скобках в списке через запятую перечислены
описания двух размерностей; диапазон по второму
измерению не известен и отмечен лишь двоеточием, но для правильного
подсчета опускать его нельзя
в нашем примере для массива Radius ранг,
то есть число измерений 3, так как
после dimension в скобках в списке через запятую перечислены
описания трех размерностей
- размерность – либо
указана явно, либо строится
по диапазону
по каждому измерению обязательно указание либо размерности, либо
диапазона
размерность или протяженность по выбранному измерению - это
неотрицательное число, указывающее на количество возможных значений
индекса по этому измерению
в нашем примере для массива Dlina число строк равно 5 (размерность по
первому измерению), а число столбцов неизвестно (размерность по
второму измерению)
в нашем примере для массива Radius число строк, равное
5, подсчитывается по диапазону -2:2; число столбцов, равно 3; число таблиц тоже 3 и
совладает с верхней границе диапазона 1:3
- диапазон – либо
указан явно, либо строится
по размерности
по каждому измерению обязательно указание либо размерности, либо
диапазона, последнего даже в виде одного лишь двоеточия
диапазон возможных значений индекса задается указанием нижней : верхней границ индекса;
в том случае, когда нижняя граница опущена, элементы нумеруются с 1 и
верхняя граница совпадает с размерностью; границы - целые числа,
индекс изменяется через 1
в нашем примере и для массива Radius и для массива Dlina размерность
по первому измерению одинакова, то есть число строк равно 5, но диапазон
разный - строки в массиве Radius нумеруются с 1 до 5, а в массиве Dlina от -2 до 2
в нашем примере для массива Radius нижняя граница диапазона номеров таблиц опущена вместе с двоеточием, по
умолчанию она; принимается; равной 1; поэтому и число
строк и число таблиц изменяются в одном и том же диапазоне от 1 до 3
в нашем примере диапазон по второму измерению для массива Dlina не известен и отмечен лишь двоеточием,
опустить которое нельзя
- форма массива – это
перечисление или вектор всех размерностей массива,
форма важнейшая характеристика, которая определяет порядок размещения
элементов в памяти - 1-й индекс самый быстрый, 2-й - медленнее .. самый
медленный – последний
в частности, двумерный массив располагается в памяти ПК по столбцам
в нашем примере массив Radius имеет форму
(5,3,3), а форма массива Dlina известна не до конца
(5,?)
в нашем примере массив Radius и Ploschad имеет одну и ту же форму (5,3,3), не смотря на
то, что имеют разный тип и разный диапазон; индексов, поэтому Ploschad=2*3.14*Radius**2 вполне допустимая формула, опирающаяся на один и
тот же порядок размещения элементов
массивов Radius и
Ploschad в памяти ПК
в нашем примере массив Radius и Dlina имеет
разный ранг, а значит и разную несовместимую форму, поэтому формула Dlina =2*3.14*Radius недопустима
- число элементов
массива равно произведению всех размерностей массива, перечисленных в форме
массива
в
нашем примере массив Radius
имеет форму (5,3,3), число
элементов=5*3*3=45
в нашем примере форма массива Dlina известна не до конца (5,?) и число элементов не
подсчитать
- объем памяти, занимаемой
массивом, равен памяти, приходящейся на один элемент, помноженной на число
элементов, ограничивается лишь объемом доступной памяти компьютера
в
нашем примере для массива Radius объем памяти=2*45=90 (байтов), поскольку integer*2 - это 2 байта на элемент, а число элементов=45
в нашем примере для массива Dlina объем памяти не подсчитать, так как неизвестно число элементов, вследствие
того, что неизвестно число столбцов (5,?)
- когда выделяется память
под массив
·
под статический массив – при запуске программы резервируется объем памяти, подсчитанный
при компиляции
массив с фиксированной размерностью,
массив с переменной размерностью- память резервируется в вызывающей
программе, а перераспределяется в вызываемой ПП
в нашем примере массив Radius - статический, все его размерности фиксированы,
потребуется неизменный объем памяти в 90 байтов
·
под динамический массив – в процессе выполнения программы, при
компиляции объем памяти не известен
массив с атрибутом allocatable - наделяемый памятью
в операторе allocate,
автоматический
массив, память под который выделяется в момент
вызова подпрограммы
в нашем примере массив Dlina динамический, так как его форма неизвестна (5,?), массив
необходимо описывать с атрибутом allocatable, чтобы вернуться к вопросу
о наделении его памятью позже при выполнении программы, когда станет известно
число столбцов
- прочие атрибуты
в нашем примере атрибут Save для массива Radius исключает попадание массива в стековую память ПК
Описание размерностных характеристик массива
DIMENSION - оператор или атрибут для
описания размерностей, диапазонов изменения индексов, ранга, и формы
массива.
Атрибут dimension в Ф-90 (оператор в Ф-77) описывает все
размерностные характеристики массива. Оператор описания с этим атрибутом должен располагаться в программе до первого
выполняемого оператора
Оператор описания, характерный для программ в стиле Фортран-77 пишется, как
в прмерах
·
dimension X(60) !
одномерный массив из 60 элементов
·
dimension g(10,20)
! матрица или двумерный массив формы (/ 10,20 /) , 10 строк, 20
столбцов
В Фортране-77 Real и dimension являются не атрибутами, а
операторами, допускается совмещать описание Real X и dimension
X(60), опуская dimension. В этом случае то, что X-массив не
явно описано dimension, а лишь косвенно видно из X(60).
В Фортране-77 допускается писать одно описание
|
Вместо двух описаний
|
Real X(60)
|
Real X
dimension X(60)
|
В скобках после атрибута dimension (после имени объекта в операторе dimension) перечисляются описания
всех измерений массива. Число описанных
измерений определяет ранг массива. Любое измерение массива можно описать
тремя способами:
- неявно путем задания диапазона индексов cнач:cкон
, где cнач £
cкон
для любого значения индекса i в программе должно выполняться соотношение cнач£ i £cкон
,
cнач ,cкон -целые - могут быть константами,
константными выражениями, параметрами ПП или выражениями, куда входят
параметры ПП
например dimension L(10:100)
- явным заданием размерности в виде cкон,
подразумевая cнач=1, для любого значения индекса i в программе
должно выполняться соотношение 1£
i £cкон,
например, dimension z(1000)
- указанием неизвестной размерности в виде двоеточия
– подразумевается, что определение размерности отложено до выполнения
программы используется для динамических массивов, объявляемых с атрибутом
allocatable, что переводится как массив, наделяемый памятью в
операторе allocate и освобождающий память в deallocate
Для того чтобы программу сделать более гибкой
- вместо констант используют
константные выражения из явных и именованных констант, чтобы легко
изменять размерности многих массивов, изменяя централизованно лишь один
параметр, например
integer, parameter :: p=20
integer, dimension(1:p+1,
1:p+1) :: M
integer, dimension(
0 : 2*p-1 ) :: L , Q
- вместо констант используют
переменные целого типа, которые являются параметрами ПП для массивов с
переменной размерностью и автоматических массивов
- в MS-Fortran 5.1
используют метакоманду $debug, чтобы обеспечить контроль
соотношения cнач£
i £cкон (с некоторым
замедлением программы), с выдачей сообщения о его нарушении в виде
"subsript out of range"
- в FPS 4.0 для слежения за индексами
используют режим отладки (проект вида debug)
Только говоря о явно описанной форме массива, как, например, в
операторе dimension M(2,3), в скобках указывают количество
строк и столбцов, в остальных случаях упоминаются значения
индексов, так, например
Real M; dimension M(2,3) ! в скобках
указано 2-количество строк, 3-количество столбцов
read(*,*) M(2,3) ! в скобках указана позиция одного единственного
читаемого элемента массива внутри массива
Позиция задается указанием 2-ой строки 3-его столбца в виде переменной с
индексами M(2,3). В примере велено читать не всю матрицу, а один единственный
элемент из 2-й строки, 3-его столбца.
read(*,*) M
! сравни - читать весь массив по
столбцам
Предупреждение:
элемент неописанного массива воспринимается компилятором как
функция с параметрами - при компиляции нет аварийной ситуации и нет сообщений,
но при компоновке получим сообщение "имя_массива
- Undefined reference" – неопределенная ссылка, из-за неудачной попытки
найти среди стандартных программ "псевдофункцию с именем массива".
Массивы и элементы массивов в формулах
Практически везде, где в формулах используется простая переменная, может быть
использована и переменная с индексами.
В фортране-90 (частично и в MS Фортране 5.1) сделано важное обобщение:
практически везде, где используется простая переменная, может быть использован
массив
real X(11), Y(11), Z(-5:5); Z = sin(X/Y+0.5)/4
+ 2.1
Непременное условие: все операнды, упомянутые в формуле с массивами – это
либо массивы одной и той же формы, либо скаляры (переменные и константы),
совместимые по форме с массивами любой формы.
Важная особенность – порядок обработки
элементов массива стандартом не оговаривается, например, можно считать, что
последовательно или параллельно. Последнее обстоятельство важно для отладки
программы на любом компьютере – хоть на ПК с единственным процессором, хоть на
суперкомпьютере со многими процессорами, где вычисления могут быть
распараллелены. Связь с конкретными возможностями “железа” отнесена к
компетенции компилятора.
Атрибуты и операторы в Фортране-77 и в Фортране
–90
В Фортране-77 атрибутов нет, есть только операторы.
В MS-Фортране 5.1 в опережение стандарта Фортран–90 появились атрибуты, которые
писали в квадратных скобках после имени объекта,
например, real*8 Dlina [ allocatable ] ( -2:2, : )
Основу описаний в Фортране-90 составляют атрибуты, но для
преемственности сохраняется форма оператора.
Атрибут
|
Назначение
|
Фортран-77
|
Фортран –90
|
DATA
|
Начальные значения объектов
|
Оператор
|
Как атрибут не пишется, однако инициализация всегда возможна.
Как оператор сохранен.
|
PARAMETER
|
Именованная константа
|
Оператор
|
Атрибут/оператор
|
ALLOCATABLE
|
Динамический объект
|
В MS-Фортране 5.1 [Атрибут] в
квадратных скобках после имени
|
Атрибут
|
SAVE
|
Сохраняемый объект
(вне стека)
|
В MS-Фортране 5.1 [Атрибут] в
квадратных скобках после имени
|
Атрибут
|
INTENT
|
Тип связи параметра:
(IN)-входной,
(OUT)- выходной,
(INOUT) – вход-выходной
|
Нет
|
Атрибут
|
OPTIONAL
|
Необязательный параметр процедуры
|
Нет
|
Атрибут
|
PUBLIC
|
Общедоступный объект модуля
|
Нет
|
Атрибут
|
PRIAVITE
|
Локальный объект модуля
|
Нет
|
Атрибут
|
POINTER
|
Указатель
|
Нет
|
Атрибут
|
TARGET
|
Объект ссылки
|
Нет
|
Атрибут/оператор
|
В Фортран –90 лучше писать атрибуты, а не операторы, потому что:
- все свойства объекта
собраны в одном определении
- переменные с одними и тем
же набором свойств (атрибутов) идут общим списком
Статическое и динамическое распределение
памяти
Объем памяти, занимаемой массивом, подсчитывается как число элементов,
помноженное на число байтов в расчете на один элемент. Число элементов равно
произведению всех размерностей массива, входящих в форму массива. Например, для
двумерного массива число элементов - это произведение числа строк на число
столбцов. В зависимости от того, когда
делается подсчет числа элементов, различают два способа наделения массива
памятью: статический - при
компиляции, динамический - при выполнении программы. Описание
массива должно быть видимо в каждой
программной единице (ПЕ), где он используется; это может быть главная
программа, подпрограмма (ПП) или модуль. В зависимости от того, где массив наделяется памятью, в каждом
из способов предусмотрено две схемы наделения массива памятью
Где описана форма массива
|
Когда массив наделяется
памятью
|
Статически –
при запуске программы
|
Динамически –
при выполнении программы
|
Форма описана в той же ПЕ, где
массив наделяется памятью
|
Массив с фиксированными размерностями
|
allocatable - массив неизвестной формы
allocate - наделить памятью
deallocate – освободить память
|
Форма описана через переменные,
полученные из параметров ПП
|
Массив с переменной размерностью среди параметров:
память распределена в вызывающей ПЕ, в ПП только перераспределяется
|
Автоматический массив не числится среди параметров – он
локализован в ПП: наделяется памятью при входе, освобождается
при выходе
|
Для статического массива при компиляции известны все характеристики.
Объем памяти под статический массив подсчитывается по описанию массива при компиляции
и резервируется при запуске программы. В случае, когда нужно добиться
максимального быстродействия, используют принцип статического распределения
памяти, согласно которому во время выполнения программы зарезервированная
память не освобождается и не изменяется! Там, где размерности
массивов указаны только константами либо константными выражениями, используется
принцип статического распределения памяти. Массив с переменной размерностью
спрятан в подпрограмме и обсуждается позже.
Для динамического массива при компиляции известны не все
характеристики, часто известен лишь ранг (его обязательно надо указывать).
Объем памяти под динамический массив при компиляции не может быть
подсчитан и при запуске программы память под него не может быть зарезервирована.
В случае, когда Вы хотите добиться максимальной гибкости в использовании
памяти, используйте принцип динамического распределения памяти, согласно
которому именно во время выполнения программы подсчитывается необходимый объем
памяти под массив, запрашивается и после использования освобождается! Там,
где обозначен только ранг,
а одна или несколько размерностей массива не известны, используется принцип динамического
распределения памяти. В Фортран–90
помимо динамических массивов с атрибутом в allocatable
в подпрограммах допускаются беззаботные автоматические
массивы, которые и обсуждается позже.
Динамический (не автоматический) массив надо описать с атрибутом allocatable.
Это означает, что при компиляции точно известен только ранг а форма
известна не до конца (для неизвестной размерности пишут “:” вместо диапазона индексов). При запуске программы массив памятью
не наделяется. Когда будут известны все размерности, будет подсчитан и выделен
необходимый объем памяти при исполнении специального оператора allocate.
Программист сам вручную выделяет память в операторе allocate и
освобождает память в операторе deallocate. В MS-Фортране в расширение стандарта Фортран-77 также имеется
атрибут allocatable,
который пишется в квадратных скобках после имени массива. Переход на
такое ручное управление требует большего опыта и ответственности. Кроме того,
на все это требуется дополнительное время!
Размещение массивов в памяти компьютера
Размещение массивов в памяти
компьютера определяется формой массива:
·
массивы
одной формы имеют равное количество элементов, которые хранятся в памяти в
одном и том же порядке
·
для
массивов разной формы порядок следования элементов разнится, даже если они
имеют равное количество элементов
Примеры на сравнение формы массивов:
real,
dimension(4:5,-1:1,0:9) :: c,d !
форма (2,3,10) рассчитывается по описаниям размерностей
real, dimension(2,3,10) :: b ! b и c,d – одной формы, хранятся в памяти в одном и том же порядке
real, dimension(2,3)
:: D ;
real, dimension(3,2)
:: M
! D и M – разной формы, хотя оба содержат по 6 элементов
real, dimension(2,0) :: E ; real, dimension(0,2) :: S ! S и E – разной формы, хотя оба не содержат
элементов
Понятие формы важно, так как именно она характеризует порядок размещения
элементов в памяти. Например, можно написать b=c ; d=2*a + sin(b), не заботясь
о порядке обработки элементов массива.. В большинстве случаев так оно и есть, и
программисту вовсе и не надо знать, как элементы массива располагаются в памяти
компьютера друг относительно друга, Это
правильно, так как позволяет распараллеливать вычисления в многопроцессорных
системах!
Однако когда в/из массива
передаются значения, то подразумевается порядок следования, соответствующий
размещению элементов в памяти компьютера. Этот порядок стандартизован в Фортране:
·
для одномерного массива - по возрастанию
индекса, например
dimension X(10) ! эквивалентны по действию 3 варианта
read(1,*) X
read(1,*) X(1), X(2), X(3), X(4), X(5), X(6), X(7), X(8), X(9), X(10)
read(1,*) X(1:10)
·
для двумерного массива - по столбцам, например,
dimension N(2,3) ! читать весь массив - понимают как
read(1,*) N ! чтение по
столбцам, как хранится в памяти
read(1,*) N(1,1), N(2,1), N(1,2),
N(2,2), N(1,3), N(2,3)
read(1,*) N(1:2,1), N(1:2,2), N(1:2,3)
·
вообще для многомерного массива - самый быстрый
- 1-ый индекс, медленнее - 2-ой, ... наконец, самый медленный - последний,
каждый из индексов пробегает все возможные значения по возрастанию, например,
dimension P(2,2,2)
read(1,*) P ! читать весь массив - понимают как
read(1,*) P(1,1,1), P(2,1,1), P(1,2,1), P(2,2,1), P(1,1,2),
P(2,1,2), P(1,2,2), P(2,2,2)
read(1,*) P(1:2,1,1), P(1:2,2,1), P(1:2,1,2), P(1:2,2,2)
Перечислим случаи, когда подразумевается порядок следования, соответствующий
размещению элементов массива в памяти компьютера:
- при подготовке данных для
ввода и просмотре результатов вывода
- при написании форматов
вывода
- при задании начальных
значений для элементов массива
- при передаче массива с переменными размерностями в
подпрограмму, на чем основан механизм перераспределения памяти
Не следует путать вопрос о порядке ввода с вопросом о подготовке данных.
Например, вводя матрицу оператором read(*,*) N, соблюдая один и тот
же порядок следования элементов
N(1,1), N(2,1), N(1,2), N(2,2), N(1,3), N(2,3) можно
расположить по-разному:
1) все числа в одной строке 11,21,12,22,13,23
2) по одному числу в строке
11
21
12
22
13
23
3) по два числа в строке
11,21
12,22
13,23
4) по 3 числа в строке
11,21,12
22,13,23
В то же время при форматном вводе
dimension N(2,3)
read(1, '( 2i3)' ) N ! числа можно расположить только по два числа в
строке, как указано в 2i3
11 21
12 22
13 23
Пример 2 "Ловушка" для начинающих. Для матрицы сумма элементов 1ой
строки Sum=11+12+13=36.
Программа расчета Sum у начинающего может
выглядеть так:
integer m1Sum,
M(3,3)
data M/ 11,12,13, 21,22,23, 31,32,33 /
do k = 1,3
m1Sum = m1Sum + M(1,k)
write(*,*) M(1, k) !
вставим просто для контроля
end do
write(*,'(3i3)' ) M
write(*,* ) 'Sum of M =', m1Sum
end
При выполнении этой программы получим на первый взгляд неожиданный результат
Sum=11+21+31=63. Причина - перепутаны
строки и столбцы в data, что часто делают начинающие. Но больше всего
их запутывает печать "правильной" матрицы в write(*,'(3i3)' ) M - на самом деле при печати еще раз перепутаны строки и столбцы.
Исправим программу, изменив в ней
data M / 11,21,31, 12,22,32, 13,23,33 / и печать матрицы по строкам, как
будет показано ниже.