Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
современный фортран , Бортеньев.pdf
Скачиваний:
242
Добавлен:
26.03.2015
Размер:
2.34 Mб
Скачать

О. В. Бартеньев. Современный ФОРТРАН

end if

! выполняется до тех пор, пока не

end

! выполнены все замены sub1 на sub2

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

Пример. Вычислить факториал числа n.

program fact

 

integer n /5/, ifact

 

write(*, *) ' 5! = ', ifact(n)

! 5! = 120

end

 

recursive function ifact(n) result (fav)

integer fav

! В операторе объявления используется

integer, intent(in) :: n

! не имя функции ifact, а имя результата fav

if(n <= 1) then

 

fav = 1

 

else

! Рекурсия продолжается, пока n > 1

fav = n * ifact(n - 1)

end if

 

end

 

Тип результата рекурсивной функции можно задать и в ее заголовке, например:

recursive integer function ifact(n) result (fav)

или:

integer recursive function ifact(n) result (fav)

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

8.18. Формальные процедуры

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

Формальные процедуры используются в задачах, решаемых для разных функций. Например, поиск экстремума, корня уравнения, вычисление определенного интеграла и т. д. В таких случаях создается процедура решения типовой задачи для широкого класса функций, в которую конкретная функция передается как фактический параметр.

Имя рассматривается как имя внешней процедуры, если оно обладает атрибутом EXTERNAL. И рассматривается как имя встроенной процедуры, если имеет атрибут INTRINSIC. Если это имя используется в качестве фактического параметра процедуры, то соответствующим формальным

266

8. Программные единицы

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

Атрибуты EXTERNAL и INTRINSIC могут иметь и иное применение. В частности, можно описать с атрибутом INTRINSIC все используемые в блоке видимости встроенные процедуры, что сделает очевидным их применение и позволит избежать дублирования их имен локальными объектами данных.

8.18.1. Атрибут EXTERNAL

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

EXTERNAL name [, name] ...

type-spec, EXTERNAL [, attrs] :: name [, name] ...

type-spec - любой оператор объявления типа.

name - имя внешней процедуры. Не может быть именем операторной функции.

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

Также атрибут EXTERNAL применяется при замене встроенной функции на пользовательскую функцию с тем же именем (разд. 8.12.2). Если в некоторой программной единице имя объекта имеет атрибут EXTERNAL и совпадает с именем встроенной процедуры, то такая встроенная процедура в этой программной единице недоступна.

Нельзя задать атрибут EXTERNAL функции с атрибутом TARGET. Процедура неявно обладает атрибутом EXTERNAL, если к ней явно

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

Пример. Написать функцию поиска корня уравнения x = f(x) с заданной точностью eps на отрезке [a, b] методом простых итераций. Начальное

267

real function fx2(x) real x
fx2 = (exp(-x) - sqrt(exp(x)) + 3.7) / 3.0 end function fx2
! Процедура поиска корня уравнения x = f(x) real function root(fx, a, b, eps)
real :: fx, a, b, eps, x, x0 ! fx - формальная процедура-функция
integer :: k, itmax = 100 ! itmax - предельно допустимое число итераций
268

О. В. Бартеньев. Современный ФОРТРАН

приближение x0 = (a + b)/2. Используя эту функцию, найти на отрезке [0, 3] с точностью eps = 0.0001 корни уравнений

x =1/(1,2arctgx + x +1)

(ответ: x = 0.5435)

и

 

x = (ex ex +3,7) / 3

(ответ: x = 0.8614).

Алгоритм:

1°. Начало.

2°. Задать начальное приближение x0, приняв, например, x0 = (a + b)/2. 3°. Положить x = f(x0).

4°. Пока |x - x0| > eps, выполнить: x0 = x

x = f(x0)

конец цикла 4°.

5°. Принять в качестве решения последнее значение переменной x. 6°. Конец.

Проиллюстрируем метод простых итераций на рис. 8.1.

y

y = x

 

 

 

 

y = f (x)

 

 

 

 

x

0

a

x0

b

Рис. 8.1. Метод простых итераций

 

Условия сходимости метода простых итераций: |f '(x)| < 1 и f '(x) < 0. Текст программы нахождения корней заданных функций:

real function fx1(x) ! Функции с исходными уравнениями real x

fx1 = 1.0/(1.2 * atan(x) + sqrt(x + 1.0)) end function fx1

8. Программные единицы

x0 = (a + b)/2.0 x = fx(x0)

k = 0

do while(abs(x - x0) .gt. eps .and. k < itmax) k = k + 1

x0 = x

x = fx(x0) end do root = x

end function root program firo

!Вариант раздела описаний с интерфейсным блоком

!real root

! interface

! Заданные в интерфейсном блоке

!

real function fx1(x)

! процедуры обладают атрибутом

!

real x

! EXTERNAL, и их можно использовать

!

end function fx1

! в качестве параметров процедур

!real function fx2(x)

!real x

!end function fx2

!end interface

!Вариант задания атрибута EXTERNAL в операторе описания real, external :: fx1, fx2, root

write(*, *) 'Корень функции fx1: ', root(fx1, 0.0, 2.0, 1.0e-4) write(*, *) 'Корень функции fx2: ', root(fx2, 0.0, 2.0, 1.0e-4)

end program firo

Замечание. Использованный критерий останова |xn - xn - 1| ≤ ε в общем

случае ошибочен и должен быть заменен на

 

xn xn1

 

1q

ε , где q |f '(x)|

 

 

q

[7].

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

8.18.2. Атрибут INTRINSIC

Атрибут INTRINSIC означает, что обладающее им имя является родовым или специфическим именем встроенной процедуры. Родовое имя встроенной процедуры не допускается в качестве фактического параметра, а должно быть использовано ее специфическое имя. Так, недопустимо употреблять в качестве параметра родовое имя функции LOG. Вместо него, например при работе с типом REAL(4), следует описать с атрибутом INTRINSIC имя ALOG и применять затем это специфическое имя в качестве параметра процедуры.

Задание атрибута может быть выполнено как отдельным оператором, так и в операторе описания типа.

INTRINSIC список имен

type-spec, INTRINSIC [, attrs] :: список имен

269

О. В. Бартеньев. Современный ФОРТРАН

список имен - одно или более имен встроенных процедур (в случае нескольких имен они разделяются запятыми). Имя не может одновременно иметь атрибуты INTRINSIC и EXTERNAL. Атрибут INTRINSIC не могут иметь имена определенных пользователем процедур.

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

Real

для

REAL(4) и REAL(8);

Cmp

для

COMPLEX(4) и COMPLEX(8);

Cmp(4)

для

COMPLEX(4);

Cmp(8)

для

COMPLEX(8).

В графе "Типы функций" указаны типы, которые функция имеет, когда она используется в качестве фактического параметра процедуры. Эта информация существенна, когда специфическое и родовое имена функции совпадают. Если родовое имя используется в выражении, то тип функции определяется типом ее параметров.

Таблица 8.3. Специфические имена, которые допускаются в качестве фактических параметров

Описание функции

Форма вызова с

Специфи-

Типы

Типы

 

родовым именем

ческие имена

аргументов

функций

 

 

 

 

 

Абсолютное значение a,

SIGN(a, b)

ISIGN

Integer

Integer(4)

умноженное на знак b

 

SIGN

Real

Real(4)

 

 

DSIGN

Real(8)

Real(8)

MAX(x - y, 0)

DIM(x, y)

IDIM

Integer

Integer(4)

 

 

DIM

Real

Real(4)

 

 

DDIM

Real(8)

Real(8)

x * y

DPROD(x, y)

DPROD

Real

Real(8)

 

 

 

 

 

Усечение

AINT(a)

AINT

Real

Real(4)

 

 

DINT

Real(8)

Real(8)

Ближайшее целое

ANINT(a)

ANINT

Real

Real(4)

 

 

DNINT

Real(8)

Real(8)

Ближайшее число типа

NINT(a)

NINT

Real

Integer(4)

INTEGER

 

IDNINT

Real(8)

Integer(4)

Абсолютная величина

ABS(a)

IABS

Integer

Integer(4)

 

 

ABS

Real

Real(4)

 

 

DABS

Real(8)

Real(8)

 

 

CABS

Cmp(4)

Real(4)

 

 

CDABS

Cmp(8)

Real(8)

270

8. Программные единицы

Остаток по модулю p

MOD(a, p)

MOD

Integer

Integer(4)

 

 

AMOD

Real

Real(4)

 

 

DMOD

Real(8)

Real(8)

Мнимая часть

AIMAG(z)

AIMAG

Cmp

Real(4)

 

 

IMAG

Cmp(4)

Real(4)

 

 

DIMAG

Cmp(8)

Real(8)

Комплексное сопряжение

CONJG(z)

CONJG

Cmp(4)

Cmp(4)

 

 

DCONJG

Cmp(8)

Cmp(8)

Квадратный корень

SQRT(x)

SQRT

Real

Real(4)

 

 

DSQRT

Real(8)

Real(8)

 

 

CSQRT

Cmp(4)

Cmp(4)

 

 

CDSQRT

Cmp(8)

Cmp(8)

Экспонента

EXP(x)

EXP

Real

Real(4)

 

 

DEXP

Real(8)

Real(8)

 

 

CEXP

Cmp(4)

Cmp(4)

 

 

CDEXP

Cmp(8)

Cmp(8)

Натуральный логарифм

LOG(x)

ALOG

Real

Real(4)

 

 

DLOG

Real(8)

Real(8)

 

 

CLOG

Cmp(4)

Cmp(4)

 

 

CDLOG

Cmp(8)

Cmp(8)

Десятичный логарифм

LOG10(x)

ALOG10

Real

Real(4)

 

 

DLOG10

Real(8)

Real(8)

Синус

SIN(x)

SIN

Real

Real(4)

 

 

DSIN

Real(8)

Real(8)

 

 

CSIN

Cmp(4)

Cmp(4)

Синус (аргумент

SIND(x)

SIND

Real, Cmp

Real(4)

в град.)

 

DSIND

Real(8)

Real(8)

Косинус

COS(x)

COS

Real

Real(4)

 

 

DCOS

Real(8)

Real(8)

 

 

CCOS

Cmp(4)

Cmp(4)

 

 

CDCOS

Cmp(8)

Cmp(8)

Косинус (аргумент

COSD(x)

COSD

Real, Cmp

Real(4)

в град.)

 

DCOSD

Real(8)

Real(8)

Тангенс

TAN(x)

TAN

Real

Real(4)

 

 

DTAN

Real(8)

Real(8)

Тангенс (аргумент

TAND(x)

TAND

Real

Real(4)

в град.)

 

DTAND

Real(8)

Real(8)

Котангенс

COTAN(x)

COTAN

Real

Real(4)

 

 

DCOTAN

Real(8)

Real(8)

Арксинус

ASIN(x)

ASIN

Real

Real(4)

 

 

DASIN

Real(8)

Real(8)

271

О. В. Бартеньев. Современный ФОРТРАН

Арксинус (результат

ASIND(x)

ASIND

Real

Real(4)

в град.)

 

DASIND

Real(8)

Real(8)

 

 

 

 

 

Арккосинус

ACOS(x)

ACOS

Real

Real(4)

 

 

DACOS

Real(8)

Real(8)

Арккосинус (результат

ACOSD(x)

ACOSD

Real

Real(4)

в град.)

 

DACOSD

Real(8)

Real(8)

Арктангенс

ATAN(x)

ATAN

Real

Real(4)

 

 

DATAN

Real(8)

Real(8)

Арктангенс (результат

ATAND(x)

ATAND

Real

Real(4)

в град.)

 

DATAND

Real(8)

Real(8)

Арктангенс (y/x)

ATAN2(y, x)

ATAN2

Real

Real(4)

 

 

DATAN2

Real(8)

Real(8)

Арктангенс (y/x)

ATAN2D(y, x)

ATAN2D

Real

Real(4)

(результат в град.)

 

DATAN2D

Real(8)

Real(8)

Гиперболический синус

SINH(x)

SINH

Real

Real(4)

 

 

DSINH

Real(8)

Real(8)

Гиперболический косинус

COSH(x)

COSH

Real

Real(4)

 

 

DCOSH

Real(8)

Real(8)

Гиперболический тангенс

TANH(x)

TANH

Real

Real(4)

 

 

DTANH

Real(8)

Real(8)

Текстовая длина

LEN(string)

LEN

Character

Integer(4)

 

 

 

 

 

Начальная позиция

INDEX(s, sub)

INDEX

"

"

 

 

 

 

 

В качестве параметров, даже после их объявления с атрибутом INTRINSIC, не могут быть использованы родовые имена встроенных процедур, а также специфические имена приведенных в табл. 8.4 встроенных процедур.

Таблица 8.4. Специфические имена, не допускаемые в качестве фактических параметров

Описание функции

Форма вызова с

Специфичес

Типы

Типы

 

родовым именем

кие имена

аргуметов

функций

 

 

 

 

 

Преобразование в целый

INT(a)

INT

Real, Cmp

Integer

тип

 

IFIX

Real(4)

Integer(4)

 

 

IDINT

Real(8)

Integer

Преобразование в

REAL(a)

REAL

Integer

Real

вещественный тип

 

FLOAT

Integer

Real

 

 

SNGL

Real(8)

Real

 

 

DREAL

Cmp(8)

Real(8)

Мнимая часть

AIMAG(z)

IMAG

Cmp(4)

Real(4)

 

 

 

 

 

MAX(a1, a2, ...)

MAX(a1, a2, ...)

MAX0

Integer

Integer

 

 

 

 

 

272

! Читаем параметры видеоокна
! numxpixels - число пикселей по оси x ! numypixels - число пикселей по оси y ! Рисуем оси координат

8. Программные единицы

 

 

AMAX1

Real

Real

 

 

DMAX1

Real(8)

Real(8)

 

 

AMAX0

Integer

Real

 

 

MAX1

Real

Integer

MIN(a1, a2, ...)

MIN(a1, a2, ...)

MIN0

Integer

Integer

 

 

AMIN1

Real

Real

 

 

DMIN1

Real(8)

Real(8)

 

 

AMIN0

Integer

Real

 

 

MIN1

Real

Integer

Пример. Построить графики функций sinx и cosx на отрезке [-π, π].

Для работы в графическом режиме необходимо создать проект как приложение QuickWin или Standard Graphics. Для доступа к процедурам графической библиотеки выполняется ссылка на модуль MSFLIB.

В графическом режиме физическая система координат видового окна начинается в его верхнем левом углу. Для построения графика используем оконную систему координат, расположив начало системы координат в центре окна. Оконная система координат позволяет выполнять графические построения, оперируя реальными координатами. Размеры окна вывода по осям x и y установим равными половине соответствующих размеров видеоокна. Для определения последних воспользуемся функцией GETWINDOWCONFIG. Назначение использованных графических процедур можно понять из размещенного в тексте программы комментария. Их подробное описание дано в [1].

use msflib

 

intrinsic dsin, dcos

! Используем специфические

logical res

! имена встроенных функций

integer(2) status2, XE, YE

! XE,YE - размеры экрана в пикселях

real(8) dx

! Используем двойную точность

logical(2) finv /.true./

! Ось y направлена снизу вверх

real(8), parameter :: pi = 3.14159265 type(windowconfig) wc

! Автоматическая настройка конфигурации окна data wc.numxpixels, wc.numypixels, wc.numtextcols, &

wc.numtextrows, wc.numcolors, wc.fontsize / 6*-1 / wc.title = "Встроенные функции как параметры процедуры"C res = setwindowconfig(wc)

res = getwindowconfig(wc) XE = wc.numxpixels

YE = wc.numypixels call axis( )

!Задание видового порта размером XE/2 * YE/2 в центре видеоокна call setviewport(XE/4_2, YE/4_2, 3_2*XE/4_2, 3_2*YE/4_2)

!Оконная система координат (ОСК)

status2 = setwindow(finv, -pi, -1.0_8, pi, 1.0_8)

273