ВУЗ: Не указан
Категория: Не указан
Дисциплина: Не указана
Добавлен: 06.12.2023
Просмотров: 341
Скачиваний: 6
ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.
7.8
Функции сдвига массива
Функция cshift ( array, shift [, dim]) — циклический сдвиг.
Функция eoshift( array, shift [, boundary] [,dim]) — нециклический.
Здесь:
1. array — массив, для которого необходим сдвиг позиций.
2. shift — аргумент, указывающий величину сдвига. В простейшем случае это — скаляр, так как величина подвижки позиций элементов одномерного массива всегда одно целое число. Если же сдвигаемый массив, например, матрица, то shift должен быть вектором с коли- чеством элементов равным либо числу строк, либо числу столбцов сдвигаемого. В этом случае каждый элемент shift указывает вели- чину сдвига по каждому из столбцов или строк соответственно. Для для многомерного сдвигаемого массива аргумент shift — массив с размерностью на единицу меньшей размерности сдвигаемого.
3. boundary — скаляр (или массив с размерностью на единицу мень- шей размерности array), который указывает, на какие значения должны замениться элементы с позициями вне допустимого диа- пазона.
4. dim — скаляр целого типа, задающий номер измерения, по которому должна произойти подвижка.
program tshift; implicit none; integer :: i, m(4)=(/(i,i=1,4)/), k(4)
integer j, n(4,4) /1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16/, n1(4,4)
write(*,’(a,4i5)’) ’
вектор m до смещения: ’,m write(*,’("Циклический cshift-сдвиг позиций вектора m: ")’)
do i=-4,4; k=cshift(m,i,1); write (*,’(a,i2,4i5)’) "i=",i,k; enddo write(*,’("Нециклический eoshift-сдвиг позиций вектора m: ")’)
do i=-4,4; k=eoshift(m,i,0,1); write (*,’(a,i2,4i5)’) "i=",i,k; enddo write(*,’(" Матрица n до смещения:")’);
write(*,’(4i4)’) ((n(i,j),j=1,4),i=1,4)
n1=eoshift(array=n,shift=(/0,-1,-2,-3/),boundary=1, dim=2)
write(*,’(" Матрица n после eoshift-смещения по ВТОРОМУ измерению:")’)
write(*,’(4i4)’) ((n1(i,j),j=1,4),i=1,4)
1 ... 11 12 13 14 15 16 17 18 ... 23
n1=eoshift(array=n,shift=(/0,-1,-2,-3/),boundary=1, dim=1)
write(*,’(" Матрица n после eoshift-смещения по ПЕРВОМУ измерению:")’)
write(*,’(4i4)’) ((n1(i,j),j=1,4),i=1,4)
end
267
вектор m до смещения:
1 2
3 4
Циклический cshift-сдвиг позиций вектора m:
i=-4 1
2 3
4
i=-3 2
3 4
1
i=-2 3
4 1
2
i=-1 4
1 2
3
i= 0 1
2 3
4
i= 1 2
3 4
1
i= 2 3
4 1
2
i= 3 4
1 2
3
i= 4 1
2 3
4
Нециклический eoshift-сдвиг позиций вектора m:
i=-4 0
0 0
0
i=-3 0
0 0
1
i=-2 0
0 1
2
i=-1 0
1 2
3
i= 0 1
2 3
4
i= 1 2
3 4
0
i= 2 3
4 0
0
i= 3 4
0 0
0
i= 4 0
0 0
0
Матрица n до смещения:
1 5
9 13 2
6 10 14 3
7 11 15 4
8 12 16
Матрица n после eoshift-смещения по ВТОРОМУ измерению:
1 5
9 13 1
2 6
10 1
1 3
7 1
1 1
4
Матрица n после eoshift-смещения по ПЕРВОМУ измерению:
1 1
1 1
2 5
1 1
3 6
9 1
4 7
10 13 1. При сдвиге матрицы по ВТОРОМУ измерению смещается ВПРАВО
содержимое первой строки на нуль позиций, содержимое второй —
на одну позицию, третьей — на две, и четвёртой — на 3 позиции.
2. При сдвиге матрицы по ПЕРВОМУ измерению смещается ВНИЗ
содержимое первого столбца на нуль позиций, содержимое второго
— на одну позицию, третьего — на две, и четвёртого — на 3 позиции.
3. В соответствии со значением аргумента boundary на пустые места,
освободившееся после сдвига, помещается единица.
268
1 2
3 4
Циклический cshift-сдвиг позиций вектора m:
i=-4 1
2 3
4
i=-3 2
3 4
1
i=-2 3
4 1
2
i=-1 4
1 2
3
i= 0 1
2 3
4
i= 1 2
3 4
1
i= 2 3
4 1
2
i= 3 4
1 2
3
i= 4 1
2 3
4
Нециклический eoshift-сдвиг позиций вектора m:
i=-4 0
0 0
0
i=-3 0
0 0
1
i=-2 0
0 1
2
i=-1 0
1 2
3
i= 0 1
2 3
4
i= 1 2
3 4
0
i= 2 3
4 0
0
i= 3 4
0 0
0
i= 4 0
0 0
0
Матрица n до смещения:
1 5
9 13 2
6 10 14 3
7 11 15 4
8 12 16
Матрица n после eoshift-смещения по ВТОРОМУ измерению:
1 5
9 13 1
2 6
10 1
1 3
7 1
1 1
4
Матрица n после eoshift-смещения по ПЕРВОМУ измерению:
1 1
1 1
2 5
1 1
3 6
9 1
4 7
10 13 1. При сдвиге матрицы по ВТОРОМУ измерению смещается ВПРАВО
содержимое первой строки на нуль позиций, содержимое второй —
на одну позицию, третьей — на две, и четвёртой — на 3 позиции.
2. При сдвиге матрицы по ПЕРВОМУ измерению смещается ВНИЗ
содержимое первого столбца на нуль позиций, содержимое второго
— на одну позицию, третьего — на две, и четвёртого — на 3 позиции.
3. В соответствии со значением аргумента boundary на пустые места,
освободившееся после сдвига, помещается единица.
268
7.9
Функции определения положения в массиве
Функция maxloc (array [, dim] [,mask]) — возвращает вектор с коли- чеством элементов равным рангу массива array. При отсутствии необя- зательных аргументов dim и mask значение очередного элемента воз- вращаемого вектора равно индексу максимального элемента array по соответствующему измерению.
Функция minloc (array) — возвращает вектор с индексами минималь- ного элемента array по каждому измерению.
При наличии dim ищется наибольший (наименьший) элемент вдоль заданного dim измерения. Наличие логического массива-маски mask позволяет находить искомое лишь среди тех элементов array, для кото- рых значения соответствующих элементов mask равны true.
program tmaxloc; implicit none integer i, m(10) / 20, 13, -5, -8, 10, 7, 3, 26, -17, -1 /
integer j, n(3,4) / 20, 13, -5, -8, 10, 7, 3, 26, -17, -1, 0, 5 /
write(*,’(a,10i4)’) " Исходный вектор m=",m write(*,*) ’ Форма maxloc(m): shape(maxloc(m))=’,shape(maxloc(m))
write(*,’(a,i4)’) "maxloc(m)=",maxloc(m)
write(*,’(a,i4)’) "minloc(m)=",minloc(m)
write(*,’(a,i4)’) ’maxloc(m,mask=m<0)=’, maxloc(m,mask=m<0)
write(*,’(a,i4)’) ’mixloc(m,mask=m>0)=’, minloc(m,mask=m>0)
write(*,’("Исходная матрица n(3,4):")’)
write(*,*) ’ Форма maxloc(n): shape(maxloc(n))=’,shape(maxloc(n))
write(*,’(4i4)’) ((n(i,j),j=1,4),i=1,3)
write(*,*) "
maxloc(n)=",maxloc(n)
write(*,*) "
minloc(n)=",minloc(n)
write(*,*) "
maxloc(n,n<0)=",maxloc(n,n<0)
write(*,*) "
minloc(n,n>0)=",minloc(n,n>0)
write(*,*) "
minloc(n,n>=0)=",minloc(n,n>=0)
write(*,*) ’ Форма maxloc(n,1): shape(maxloc(n,1))=’,shape(maxloc(n,1))
write(*,*) "
maxloc(n,1)=",maxloc(n,1)
write(*,*) "
minloc(n,1)=",minloc(n,1)
write(*,*) ’ Форма maxloc(n,2): shape(maxloc(n,2))=’,shape(maxloc(n,2))
write(*,*) "
maxloc(n,2)=",maxloc(n,2)
write(*,*) "
minloc(n,2)=",minloc(n,2)
write(*,*) "
maxloc(n,1,n<0)=",maxloc(n,1,n<0)
write(*,*) "
minloc(n,1,n<0)=",minloc(n,1,n<0)
write(*,*) "
maxloc(n,2,n<0)=",maxloc(n,2,n<0)
write(*,*) "
minloc(n,2,n<0)=",minloc(n,2,n<0)
end
269
Исходный вектор m=
20 13
-5
-8 10 7
3 26 -17
-1
Форма maxloc(m): shape(maxloc(m))=
1
maxloc(m)=
8
minloc(m)=
9
maxloc(m,mask=m<0)=
10
mixloc(m,mask=m>0)=
7
Исходная матрица n(3,4):
Форма maxloc(n): shape(maxloc(n))=
2 20
-8 3
-1 13 10 26 0
-5 7 -17 5
maxloc(n)=
2 3
minloc(n)=
3 3
maxloc(n,n<0)=
1 4
minloc(n,n>0)=
1 3
minloc(n,n>=0)=
2 4
Форма maxloc(n,1): shape(maxloc(n,1))=
4
maxloc(n,1)=
1 2
2 3
minloc(n,1)=
3 1
3 1
Форма maxloc(n,2): shape(maxloc(n,2))=
3
maxloc(n,2)=
1 3
2
minloc(n,2)=
2 4
3
maxloc(n,1,n<0)=
3 1
3 1
minloc(n,1,n<0)=
3 1
3 1
maxloc(n,2,n<0)=
4 0
1
minloc(n,2,n<0)=
2 0
3 1. Результат maxloc(m) — вектор из одного элемента, а не скаляр.
Запись i=maxloc(m) ошибочна (слева – скаляр; справа вектор).
2. Результат maxloc(n) — вектор из двух элементов: местоположение элемента матрицы определяется двумя индексами: строки и столбца
(индекс строки – в первом элементе, индекс столбца – во втором).
3. Результат maxloc(n,1) тоже вектор, но уже из четырёх чисел, так как ищется максимальное для каждого из ЧЕТЫРЁХ столбцов.
4. maxloc под ПЕРВЫМ измерением понимает направление перехода от предыдущего столбца к очередному. после того, как для преды- дущего был найден максимальный элемент.
5. maxloc под ВТОРЫМ измерением понимает направление перехода от предыдущей строки к следующей после нахождения максималь- ного элемента. maxloc(n,2) есть вектор из трёх элементов, так как ищется максимальное для каждой строки, а их у матрицы n — три.
270
7.10
О чем узнали из седьмой главы? (второй семестр)
1. Современный ФОРТРАН предоставляет для работы с массивами набор функций, которых не было в ФОРТРАНе-77, что позволяет существенно сократить размер исходных текстов программ, обраба- тывающих массивы, и уменьшить временные затраты.
2. К справочным функциям относятся:
allocated(array),
size(array [, dim]),
shape(source)
lbound(array [, dim])
и ubound(array [, dim]).
3. К функциям редукции (массивов) относятся:
all(mask [, dim]),
any(mask [, dim]),
count(mask [, dim]),
maxval(array [, dim] [,mask]),
minval(array [, dim] [,mask]),
product(array [,dim], [,mask]),
sum(array [,dim], [,mask]).
Термин редукция (reduction — снижение, понижение, уменьшение,
сокращение, приведение) в данном контексте означает, что на вход к функции в качестве аргумента подаётся массив, а на выходе получа- ется значение с меньшим числом элементов чем имеется в массиве- аргументе (см., например, [2, 7]).
4. Функция скалярного умножения даух векторов dot_product(vector_a,vector_b)
5. Функция умножения матриц matmul(matrix_a,matrix_b).
Умножение матриц определено лишь для согласованных матриц
(т.е. число столбцов первой должно равняться числу строк второй).
6. matmul и dot_product осуществляют лишь формальное приве- дение числовых типов друг к другу, т.е. данное типа real(4) после преобразования в тип real(8) из шестнадцати десятичных цифр,
будет иметь верными лишь старших 7.
7. Перемножение матриц логического типа происходит по правилу пе- ремножения числовых (с заменой сложения дизъюнкцией, а умно- жения — конъюнкцией).
271
8. Размещаемые массивы современного ФОРТРАНа позволяют упро- стить решение задач, для которых на старом ФОРТРАНе приходи- лось использовать некие искусственные приёмы.
9. Если нужно располагать рабочие матрицы в левом верхнем углу матрицы большего размера, ОБЯЗАТЕЛЬНО включаем в список формальных аргументов соответствующих процедур переменную,
хранящую строковый размер большей матрицы, заявленный в вы- зывающей программе.
10. Современный ФОРТРАН позволяет обойтись без подобного вклю- чения, так как способен посредством функций lbound и ubound определить граничные индексы фактических аргументов, если фор- мальные перенимают их форму.
11. Функция transpose(matrix) транспонирует матрицу и возвращает результат (транспонированную матрицу) через своё имя.
12. Функция merge(tsource,fsource,mask) возвращает массив, значе- ния элементов которого равны tsource или fsource в зависимости от истинности элементов массива mask.
13. Функция pack(array,mask,[vector]) через имя pack возвращает вектор, собранный из тех и только тех элементов массива array,
для которых значения маски mask есть true.
14. Функция unpack(vector,mask,field) возвращает через своё имя массив, полученный расфасовкой содержимого элементов вектора vector в соответствии с содержимым логического массива mask той же формы, что и unpack.
15. Функция spread( source, dim, ncopies) добавляет ncopies ко- пий исходного массива source вдоль заданного измерения dim в массиве-результате spread.
16. cshift ( array, shift [, dim]) — реализует циклический сдвиг;
eoshift( array, shift [, boundary] [,dim]) — нециклический.
17. Функции maxloc и minloc — возвращают вектор с индексами со- ответствующего элемента массива array.
272
7.11
Седьмое домашнее задание (второй семестр).
Задача N 1.
Написать программу, которая помогает выяснить:
Какие значения и когда вырабатываются встроенными функциями lbound и ubound при вызове их внутри подпрограммы, формальным аргументом которой является вектор, перенимающий форму фактиче- ского аргумента.
Задача N 2
Разработать функцию, которая для заданного положительного целого находит наибольшее из чисел, получаемых циклической перестановкой двоичного представления исходного целого.
Задача N3
Разработать функцию приведения матрицы системы линейных алгеб- раических уравнений c n неизвестными к эквивалентному треугольному виду.
Задачи N 4 — 8.
Разработать функции, моделирующие работу встроенных функций,
указанных ниже, продемонстрировать их работу и оформить тестирую- щую программу так, чтобы она позволяла легко убедиться в совпадении их результатов с результатами встроенных. Разработанные функции по- местить в модуль myarray.
4. Функция my_dot_production нахождения скалярного произве- дения двух векторов.
5. Функция my_matmul (перемножение матриц).
6. Функция my_transpose (транспонирование матрицы)
7. Функция my_maxval (поиск максимального элемента матрицы с наименьшими индексами) .
8. Функция my_minloc (поиск наибольших индексов минимального элемента матрицы)
273
8
Форматирование данных ввода-вывода
Изложение материала в основном по книгам [2] и [3].
В простых программах для ввода и вывода используются операторы read(*,*) список_ввода и
write(*,*) список_вывода
Первая * в этих операторах – синоним стандартного устройства ввода- вывода (по умолчанию это — экран). Вторая * — синоним управления вводом-выводом под управлением списка ввода-вывода, т.е. способ преобразования данных в машинное представление (или из машинно- го) определяется по типам элементов, указанных в списке ввода-вывода.
Подобный способ удобен, когда результат нужен в понятной, но непри- тязательной форме, определяемой компилятором по умолчанию:
program frm1; implicit none
! Ввод-вывод под управлением integer n / 10 /
! списка ввода-вывода удобен real x /1.7/, em /9e-28/, sunm /-1.99e+33/
! удобен и тогда, когда logical b(2) /.true., .false. /
! заранее известно, что character(1) abc(3) /’a’,’b’,’c’/
! данные - это поток чисел,
integer matr(2,3) / 1, 2, 3, 4, 5, 6 /
! разделённых пробелами,
write(*,*) ’
n=’, n
! причём нам неважно, сколько write(*,*) ’
b=’, b
! чисел в каждой строке и
write(*,*) ’
abc=’, abc
! каким количеством пробелов write(*,*) ’
x=’, x
! одно число отделяется от write(*,*) ’
em=’, em
! другого (важно наличие хотя write(*,*) ’ sunm=’, sunm
! бы одного пробела для write(*,*) ’ matr=’, matr
! разделения чисел).
end program frm1
n=
10
! Здесь по умолчанию компилятор отвёл b= T F
! на целое данное десять позиций;
abc=abc
! на булево значение - две; на однобайтовый;
x=
1.7000000
! символ - одну, а на вещественное значение em=
8.99999967E-28 ! - пятнадцать (включив недостающие пробелы).
sunm=
1.99100001E+33
matr=
1 2
3 4
5 6
Обычно данные выгоднее размещать на внешнем носителе, записывая в желательном формате. Выгода — большая наглядность и возможно- сти при вводе размещать в невостребованной части строки поясняющий комментарий. Указание о месте расположения и формы записи осуществ- ляется форматированием, управляемым явным заданием формата.
274
8.1
Явное задание формата
8.1.1
Примеры
Демонстрация некоторых возможностей задания формата:
program frm2
implicit none integer n / 10 /
real x / 1.7 /, em /9e-28/, sunm / -1.991e+33 /
logical b(2) /.true., .false. /
!
character(1) abc(3) /’a’,’b’,’c’/
!
Результат работы frm2
integer matr(2,3) / 1, 2, 3, 4, 5, 6 /
!
write(*,’(1x,5x,a,i2)’)
’
n=’, n
!
n=10
write(*,’(1x,5x,a,l1,3x,l1)’)’
b=’, b
!
b=T
F
write(*,’(1x,5x,a,3a4)’)
’
abc=’, abc
!
abc=
a b
c write(*,’(1x,19x,a,f5.2)’)
’
x=’, x
!
x= 1.70
write(*,’(1x,5x,a,e9.2)’)
’
em=’, em
!
em= 0.90E-27
write(*,’(1x,5x,a,e10.3)’)
’ sunm=’, sunm !
sunm=-0.199E+34
write(*,’(1x,5x,a,6i2)’)
’ matr=’, matr !
matr= 1 2 3 4 5 6
end
В операторах write вместо второй звёздочки явно указан формат вы- вода. Синтаксически он обрамлён апострофами, т.е. представляет собой строковую константу.
1. В качестве первого элемента формата использовано сочетание двух символов 1x, что на языке оператора format означает один пробел.
1x — один из управляющих дескрипторов оператора format.
2. Дескрипторы отделяются друг от друга, т.е. строка (1x,5x) озна- чает, что при выводе сначала выводится один пробел, а затем ещё
пять. Вместо (1x,5x) можно обойтись и одним дескриптором 6x.
3. В данной программе файл вывода обозначен * (первая звездоч- ка в операторе write) и особо не описывается оператором open
(его подробно не изучали, но использовали). Тем не менее полезно знать, что при открытии файлов ФОРТРАНа первый символ фор- матной строки может трактоваться как код управления кареткой печатающего устройства (в частности, первый пробел означает пе- ревод строки и не печатается). Именно поэтому во многих старых
ФОРТРАН-программах форматная строка начиналась c 1x.
275