1
متغیرهای اندیس دار یا زیرنویس دار
2
آرایه (Array)
آرایه گروهی از متغیرها یا ثابت ها هستند که نوع آن ها یکی است و با اسم واحدی نامیده می شوند.
a(1)
a(2)
a(3)
a(4)
a(5)
Array a
حافظه رایانه
3
نمایش متغیر به صورت آرایه
Do i = 1, 100
a(i) = SQRT(a(i))
End do
جزییات حلقه فوق به صورت زیر است:
a(1) = SQRT(a(1))
a(2) = SQRT(a(2))
a(100) = SQRT(a(100))
4
دستور اعلام متغیر اندیس دار
Real, Dimension(10) :: X
Character(len = 20), Dimension(50) :: & last_name
آرایه می تواند با یک یا چند بعد معرفی شود. تعداد ابعاد یک آرایه را رتبه (rank) نامند. در مثال فوق رتبه متغیرهای X و last_name برابر یک است.
تعداد عناصر یک بعد را extent آن گویند. در متغیر X برابر 10 و در متغیر last_name برابر 50 است.
ترکیبی از rank و extent هر آرایه را شکل (shape) آن آرایه نامند. بنابراین دو آرایه دارای یک شکل هستند، اگر رتبه و تعداد عناصر هر بعد آرایه با هم یکسان باشد.
به تعداد کل درایه های یک آرایه اندازه (size) آن آرایه گویند.
5
مثال اعلام متغیر اندیس دار، یک بعد و بیش از یک بعد
R e a l, D i m e n s i o n(100) :: R
R e a l, D i m e n s i o n(10,10) :: S
R e a l :: T(10,10)
Integer, Dimension :: L(2,3)
Integer, Dimension(5) :: A, B(2,3)
R e a l, D i m e n s i o n(15) :: X
R e a l, D i m e n s i o n(3,5) :: Y, Z
به دو مثال اخیر توجه کنید. متغیر X دارای رتبه یک و متغیرهای Y,Z دارای رتبه دو هستند.
اندازه متغیرهای X و Y,Z با هم برابرند.
متغیرهای X و Y,Z دارای شکل یکسان نیستند.
extent بعد دوم متغیرهای Y,Z برابر 5 است.
6
انواع اندیس ها
فرم کلی اندیس ها به صورت زیر است.
Real,Dimension(lower_bound:upper_bound) :: array
به شرط آن که
lower_bound <= upper_bound
به مثال های زیر توجه کنید.
Real, Dimension(5) :: a1
Real, Dimension(-2:2) :: b1
Real, Dimension(5:9) :: c1
هر سه آرایه دارای شکل (shape) یکسان هستند. زیرا دارای ابعاد و extent برابرند.
در حالت کلی تعداد درایه در هر بعد را، می توان با استفاده از رابطه ساده زیر بدست آورد.
Extent = upper_bound – lower_bound+1
Real, Dimension(-2:2, 0:3)
همانطور که ملاحظه می شود هر بعد گستره مربوط به خود را دارد. گستره بعد اول 5 و گستره بعد دوم 4 است.
7
استفاده از عناصر متغیرهای اندیس دار مانند متغیرهای عادی
هر درایه از آرایه ای را می توان به صورت یک متغیر معمولی به کار برد. به مثال زیر توجه کنید.
Integer, Dimension(10) :: index
Real, Dimension(3) :: temp
دستورات کاملا درست هستند.
Index(10) = 5
Temp(3) = Real(index(1)) / 4.
Write(*,*) 'index(1) =', index(1)
8
مقداردهی اولیه درایه های یک آرایه یک بعد
همان طور که قبلا هم ذکر شد، خیلی از زمان ها لازم است که متغیرها را مقداردهی شوند. به مثال زیر توجه کنید.
Real, Dimension(10) :: array1
Do i = 1, 10
array1(i) = real(i)
End do
دستورات زیر معادل کدهای فوق است.
Real, Dimension(10) :: array1
array1 = (/1.,2.,3.,4.,5.,6.,7.,8.,9.,10./)
و بالاخره می توان عمل مقداردهی را به صورت زیر انجام داد.
Real, Dimension(10) :: array1
array1 = 0.
می توان عمل مقداردهی را حتی در دستور اعلام نیز گنجاند.
Integer, Dimension(5) :: array2 = (/1,2,3,4,5/)
ادامه مقداردهی اولیه درایه های یک آرایه یک بعد
می توان به صورت عبارت هم مقداردهی نمود. به مثال زیر توجه کنید.
Integer, parameter :: N = 3, M = 6, P = 12
Integer :: arr(1:3) = (/ N, M/N, P/N /)
توجه کنید که در مثال بالا، گذاشتن parameter اجباری است. ضمناً نمی توان در مقداردهی (/…/) از توابع استفاده نمود. اکنون مثال بالا را کمی تغییر می دهیم.
Integer, Dimension(3) :: arr
Integer :: N = 3, M = 6, P = 12
arr = (/ N, M/N, P/N /)
9
10
خطای مازاد اندیس های آرایه
هر درایه یک آرایه به یک اندیس که عدد صحیح است نسبت داده میشود. محدوده را دستور اعلام مشخص می کند.
Real, Dimension(5) :: a
در این مثال اندیس ها، اعداد از 1 تا 5 می باشند. اگر در محاسبات درایه a(6) رخ دهد. شما خطای out of bound را دریافت می کنید.
این خطای را می توان جزء خطاهای رایج کار با آرایه ها محسوب نمود. یافتن این خطا در پاره ای از موارد کار ساده ای نیست.
استفاده از مقدار ثابت در اعلام آرایه
همان طور که ملاحظه شد در ابعاد آرایه می توان اعداد صحیح مختلف را به کار برد.
همچنین می توان از یک پارامتر و یا عبارت ثابت نیز استفاده نمود.
مثال 1:
Integer, Parameter :: max_size = 100
Real, Dimension(max_size) :: array1
Real, Dimension(max_size) :: array2
Real, Dimension(max_size) :: array3
مثال 2:
Integer, Parameter :: max_size = 100
Integer, Dimension(max_size/4) :: array1
Real, Dimension(int(log(Real(max_size)))) :: & array2
11
مثال 1 برای تخصیص حداکثر
Program REVERSE
Integer :: i, n
Real, Dimension(1000) :: X
Read*, n, (X(i), i=1, n)
Do i = n, 1, -1
Print *, X(i)
End do
End program REVERSE
12
مثال 2 برای تخصیص حداکثر
اعلان های زیر مفروض است.
Integer, parameter :: L_BOUND = 3, U_BOUND = 10
Integer, Dinemsion(L_BOUND:U_BOUND) :: x
13
Do i = L_BOUND, U_BOUND
x(i) = i
End do
array x() has 3,4,5,…, 10
Do i = L_BOUND, U_BOUND
if (MOD(i,2) == 0) Then
x(i) = 0
Else
x(i) = 1
End if
End do
array x() 1 0 1 0 1 0 1 0
14
عملیات آرایه ای (1)
Implicit none
Integer :: I
Real, Dimension(4) :: a = (/1.,2.,3.,4./)
Real, Dimension(4) :: b = (/5.,6.,7.,8./)
Real, Dimension(4) :: c, d
! Element by Element addition
Do i = 1, 4
c(i) = a(i) + b(i)
End do
15
عملیات آرایه ای (2)
! Whole array addition
d = a + b
! Write out results
Write(*,100) 'c', c
Write(*,100) 'd', d
100 format(' ', A, '=', 4(F6.1,1X))
End
در این مثال آرایه ها حتما باید دارای شکل (shape) یکسان باشند.
16
عملیات آرایه ای (3)
به مثال زیر توجه کنید که یک ضرب عدد در آرایه است.
Real, Dimension(4) :: a = & (/1.,2.,3.,4./), c, d
Real :: b = 10
c = a*b
d = b*a
حتی می توان از توابع کتابخانه ای نیز به صورت زیر استفاده نمود.
Real,Dimension(4) :: a=(/-1.,2.,-3.,4./)
write(*,*) ABS(a)
یکسان
17
ورودی و خروجی در آرایه ها (2)
Write(*,1000) (i, 2*i, 3*i, i = 1, 3)
1000 format(1X, 9I6)
پاسخ در یک سطر به صورت زیر چاپ می شود.
1 2 3 2 4 6 3 6 9
حلقه do ضمنی می تواند تودرتو باشد. به مثال زیر توجه کنید.
Write(*,100) ((i, j, j = 1, 3), i = 1, 2)
100 format(1X, I5, 1X, I5)
پاسخ به صورت زیر است.
1 1
1 2
1 3
2 1
2 2
2 3
18
تفاوت بین حلقه do عادی و حلقه do ضمنی
همان طور که ملاحظه می شود، دو نوع حلقه do وجود دارد که اکنون با مثال زیر می توان تفاوت بین آن ها را مشاهده نمود.
Integer, Dimension(5) :: arr = (/1,2,3,4,5/)
Do i=1,5
Write(*,1000) arr(i), 2*arr(i), 3*arr(i)
1000 format(1X, 6I6)
End do
اکنون به همین مثال به شکل دیگر توجه کنید.
Write(*,1000) (arr(i), 2*arr(i), 3*arr(i), i = 1,5)
1000 format(1X,6I6)
19
تفاوت بین حلقه do عادی و حلقه do ضمنی
پاسخ do عادی
1 2 3
2 4 6
3 6 9
4 8 12
5 10 15
پاسخ do ضمنی
1 2 3 2 4 6
3 6 9 4 8 12
5 10 15
20
نحوه تخصیص حافظه در آرایه دو بعدی
به ماتریس زیر توجه کنید.
آرایه دو بعدی
نحوه قرار گرفتن در حافظه
21
نحوه تخصیص حافظه در آرایه سه بعدی
آرایه سه بعدی 22 2
1,1,1
2,1,1
1,2,1
2,2,1
1,1,2
2,1,2
1,2,2
2,2,2
Page one
Page two
1
2
3
Do i=1,2
Do j=1,2
Do k=1,2
………..
…………
End do
End do
End do
22
مقداردهی آرایه های دو بعدی (1)
مقداردهی با استفاده از نسبت دادن
به مثال زیر توجه کنید.
Integer, Dimension(4,3) :: istat
Do i = 1, 4
Do j = 1, 3
istat(i, j) = j
End do
End do
23
مقداردهی آرایه های دو بعدی (2)
مقداردهی با استفاده از دستور read، به مثال زیر توجه کنید.
فرض کنید که داده ها از روی فایلی به نام initial.dat خوانده شود که دارای ساختار زیر است.
1 1 1 1 2 2 2 2 3 3 3 3
کدهای برنامه به صورت زیر است.
Integer, Dimension(4,3) :: istat
Open(7, file = 'initial.dat')
Read(7,*) istat
24
مقداردهی آرایه های دو بعدی (4)
اما اگر ساختار فایل ورودی به شکل زیر بود.
1 2 3 1 2 3 1 2 3 1 2 3
کدهای برنامه به صورت زیر است.
Integer :: i, j
Integer, Dimension(4,3) :: istat
Open(7, file = 'initial.dat')
Read(7,*) ((istat(i,j), j = 1, 3), i = 1, 4)
25
زیر آرایه ها
تاکنون عملیات روی کل درایه ها یک آرایه انجام شد. اما می توان عملیات را روی زیرمجموعه ای از درایه های یک آرایه متمرکز نمود. فرم کلی آن به صورت زیر است.
subscript_1 : subscript_2 [: stride]
subscript_1 نشان دهنده اولین اندیس است.
subscript_2 نشان دهنده آخرین اندیس است.
stride نشان دهنده گام های افزایش است.
در واقع این رویه مانند یک حلقه do عمل می کند.
26
مثال زیر آرایه در یک بعد
Integer :: i = 3, j = 7
Real, Dimension(10) :: a = (/1.,-2.,3.,-4.,5.,-6.,7.,-8.,9.,-10./)
اکنون به پاسخ زیر ارایه های زیر توجه کنید.
a(:) 1.,-2.,3.,-4.,5.,-6.,7.,-8.,9.,-10.
a(i:j) 3.,-4.,5.,-6.,7.
a(i:j:i) 3.,-6.
a(i:j:j) 3.
a(i:) 3.,-4.,5.,-6.,7.,-8.,9.,-10.
a(:j) 1.,-2.,3.,-4.,5.,-6.,7.
a(::i) 1.,-4.,7.,-10.
27
مثال زیر آرایه در یک بعد
Integer :: i = 3, j = 7
Real, Dimension(10) :: a = (/1.,-2.,3.,-4.,5.,-6.,7.,-8.,9.,-10./)
اکنون به پاسخ زیر ارایه های زیر توجه کنید.
a(:) 1.,-2.,3.,-4.,5.,-6.,7.,-8.,9.,-10.
a(i:j) 3.,-4.,5.,-6.,7.
a(i:j:i) 3.,-6.
a(i:j:j) 3.
a(i:) 3.,-4.,5.,-6.,7.,-8.,9.,-10.
a(:j) 1.,-2.,3.,-4.,5.,-6.,7.
a(::i) 1.,-4.,7.,-10.
مثال زیر آرایه در دو بعد
به مثال زیر توجه کنید.
28
29
دنباله مثال قبل
30
دنباله مثال قبل
تناظر درآیه به درآیه دو ماتریس در تساوی کلی
R e a l, D i m e n s i o n(1:3,1:2) :: m a t r i c e1
R e a l, D i m e n s i o n(-1:1,0:1) :: m a t r i c e2
m a t r i c e1 = m a t r i c e2
اکنون اگر بخواهید در عملگر انتساب تفکیک درایه به درایه دو ماتریس بالا را ملاحظه کنید، به بسط زیر توجه نمایید.
m a t r i c e1(1,1) = m a t r i c e2(-1,0)
m a t r i c e1(2,1) = m a t r i c e2(0,0)
m a t r i c e1(3,1) = m a t r i c e2(1,0)
m a t r i c e1(1,2) = m a t r i c e2(-1,1)
m a t r i c e1(2,2) = m a t r i c e2(0,1)
m a t r i c e1(3,2) = m a t r i c e2(1,1)
31
سازگاری زیرآرایه ها
مثال 1:
REAL :: A(1:6, 1:8), B(0:3, -5:5), C(0:10)
A(2:5, 1:7) = B(:, -3:3) ! both have shape (4, 7)
A(4, 2:5) = B(:, 0) + C(7:) ! all have shape (4)
C(:) = B(2, 🙂 ! both have shape (11)
مثال 2:
INTEGER :: arr1(1:100), arr2(1:50), arr3(1:50)
arr1(1:100:2) = arr2 ! Sets every odd element
arr1(100:1:-2) = arr3 ! Even elements, reversed
arr1 = arr1(100:1:-1) ! Reverses the order of arr1
32
33
توابع کتابخانه ای آرایه ها
در فرترن 90 توابع کتابخانه ای قابل ملاحظه ای مربوط به بردارها تعبیه شده است. که برخی از آن ها به شرح زیر است.
SHAPE(x) ! The shape of x
RESHAPE(x, shape[, pad][, order])
SIZE(x [, Dim ]) ! The size of x
LBOUND(x [, Dim]) ! The nth lower bound of x
UBOUND(x [, Dim]) ! The nth upper bound of x
MINVAL(x) ! The minimum of all elements of x
MINLOC(x) ! The index of the minimum
MAXVAL(x) ! The maximum of all elements of x
MAXLOC(x) ! The index of the maximum
SUM(x [, Dim]) ! The sum of all elements of x
PRODUCT(x [, Dim]) ! The product of all elements of x
TRANSPOSE(x) ! The transposition of x
DOT_PRODUCT(x, y) ! The dot product of x and y
MATMUL(x, y) ! Matrix multiplication
تابع shape
این تابع شکل آرایه (بعد و گستره) را نشان می دهد. شکل عمومی به صورت زیر است.
shape(source)
مثال:
Integer, Dimension(-2:27,0:49) :: t
print*, shape(t)
خروجی عبارتست از:
30 50
34
تابع Reshape
این تابع شکل یک آرایه را عوض می کند. شکل عمومی به صورت زیر است.
Reshape(source, shape[, pad][, order])
مثال 1:
Integer, Dimension(2,2) :: A
A = Reshape((/1,2,3,4/), (/2,2/))
35
دنباله تابع Reshape
مثال 2:
Integer, Dimension(2,2) :: A
A = Reshape((/ 1,2,3,4/), (/2,2/), order=(/2,1/))
مثال 3:
B = Reshape((/ 1,2,3,4,5,6/), (/2,4/), (/0/),(/2,1/))
36
37
تابع Size
در این تابع می توان تعداد کل عناصر یک آرایه و یا یکی از ابعاد آن را به دست آورد. نحوه آن عبارتست از:
Size(source[, Dim])
مثال:
Real A(2, 3, 5)
Size(A, 1) 2
Size(A) 30
38
تابع Sum در یک بعد
در این تابع می توان مجموع عناصر یک آرایه و یا یکی از ابعاد آن را به دست آورد. نحوه آن عبارتست از:
Sum(source[, dim] [, mask])
Integer :: w(1:11) = (/7,9,-2,4,8,10,2,7,10,2,1/)
Print*, sum(w)
End
39
تابع Sum در دو بعد
I n t e g e r w(2,11)
w = r e s h a p e((/7, 9, -2, 4, 8, 10, 2, 7, 10, 2, 1, 10, 7, 7, 1, &
10,-2, -2, 7, 2, 9, -2/), (/2,11/), o r d e r = (/2,1/))
p r i n t*, s u m(w,d i m=1)
E n d
40
تابع Product
در این تابع می توان حاصل ضرب عناصر یک آرایه و یا یکی از ابعاد آن را به دست آورد. نحوه آن عبارتست از:
مثال:
Product(source[, dim][, mask])
P r i n t*, P r o d u c t(A, d i m=1) 2 12 30
P r i n t*, P r o d u c t(A, d i m=2) 15 48
41
All
دو ماتریس A و B به صورت زیر هستند.
تابع کتابخانه ای All به صورت زیر است.
A l l(m a s k[, d i m])
مقایسه روی ستون
P r i n t*, A l l(A/=B,d i m=1) T F F
مقایسه روی سطر
P r i n t*, A l l(A/=B,d i m=2) F F
42
Any
دو ماتریس A و B به صورت زیر هستند.
تابع کتابخانه ای Any به صورت زیر است.
A ny(m a s k[, d i m])
مقایسه روی ستون
P r i n t*, A n y(A/=B, d i m=1) T F T
مقایسه روی سطر
P r i n t*, A n y(A/=B, d i m=2) T T
ترانهاده یک ماتریس
تابع ذاتی transpose یک ماتریس را ترانهاده می نماید.
TRANSPOSE(X) means
در این تابع، آرایه دو بعدی (ماتریس) است ولی لزومی ندارد که ماتریس مربع باشد.
43
44
Dot_Product
در این دستور ضرب داخلی دو بردار انجام می شود.
Dot_Product(X, Y) means
این دستور فقط در بردارها (آرایه یک بعدی با طول و نوع یکسان) عمل می کند. به مثال زیر نگاه کنید.
I n t e g e r :: A1(1:6)=[1,3,5,2,4,6]
I n t e g e r :: B1(1:6)=[0,3,5,7,4,8]
C=D o t_P r o d u c t(A1, B1)
P r i n t*, C
45
MatMul
در اینجا دستور ضرب ماتریس ها به همان روش که در ریاضیات مرسوم است، انجام می شود. به عبارت دیگر اگر یک ماتریس (i,k) در یک ماتریس (k,j) ضرب شود، ماتریس حاصل (i,j) خواهد.
MatMul(X, Y) means
اکنون به مثال زیر توجه کنید.
I n t e g e r, D i m e n s i o n(2,3) :: A
I n t e g e r, D i m e n s i o n(3,2) :: B
I n t e g e r, D i m e n s i o n(2,2) :: C
A=R e s h a p e( (/1,2,3,4,5,6/), (/2,3/) )
B=R e s h a p e( (/0,7,3,4,5,8/), (/3,2/) )
C = M a t M u l(A, B)
P r i n t*, C
46
Where construct
فرض کنید می خواهید لگاریتم پاره ای از عناصر یک ماتریس را بگیرید.
Do and if construct
Do i = 1, m
Do j = 1, n
If(value(i, j) > 0.) Then
Logval(i, j) = log(value(i, j))
Else
Logval(i, j) = -99999
End if
End do
End do
WHERE construct
Where(value > 0.)
Logval = log(value)
Elsewhere
logval = -99999
End where
47
Forall construct
Do and if construct
Do i = 1, m
Do j = 1, n
If(work(i, j) /= 0.) Then
work(i, j) = 1./ work(i, j)
End if
End do
End do
Forall construct
Forall(i = 1:m, j = 1:n, work(i, j) /= 0.)
work(i, j) = 1./ work(i, j)
End Forall
48
متغیرهای اندیس دار شناور
تخصیص ایستای حافظه (static memory allocation)
تاکنون اندازه متغیرهای اندیس دار برای هر متغیر در ابتدای برنامه معین می شد. به این نحوه تخصیص، که از ابتدا تا انتهای برنامه میزان اندازه ارایه ثابت است، تخصیص ایستا گویند.
تخصیص پویای حافظه (dynamic memory allocation)
در این رویکرد حسب نیاز، حافظه به متغیر اختصاص داده می شود، بنابراین حافظه تخصیص یافته به هر متغیر اندیس دار می تواند در طول برنامه تغییر کند، که به آن تخصیص پویا گویند.
49
نحوه اعلان تخصیص شناور یا پویا
Real, Allocatable, Dimension(:) :: arr1
در اینجا یک آرایه یک بعدی اعلان شده است که اندازه بعد آن معین نشده است.
Real, Allocatable, Dimension(:,:) :: arr2
در اینجا یک آرایه دو بعدی اعلان شده است که اندازه ابعاد آن معین نشده است.
مثال:
I n t e g e r, A l l o c a t a b l e, D i m e n s i o n(:) :: n u m s
I n t e g e r :: t e m p, i, k, n_t o_s o r t
P r i n t'(A)', 'H o w m a n y n u m b e r s t o s o r t:'
R e a d*, n_t o_s o r t
a l l o c a t e( n u m s(1:n_t o_s o r t) )
D O i = 1, n_t o_s o r t
R e a d*, n u m s(i)
E n d D O
I F(A l l o c a t e d(n u m s)) D e a l l o c a t e(n u m s)