300 likes | 499 Views
Chapter 6 陣列. 設定陣列的大小,一定是整數. 陣列變數的名字. 所要使用的資料型態,可以是 integer / real / … 等等的基本型態外,還可以是自己用 type 所定義出來的自訂型態. A(1). A(2). A(3). A(10). …. A. 6-1 矩陣的宣告與使用. 陣列宣告 integer :: A(10) 宣告 10 個元素的整數陣列 A , 其元素為 A(1) 、 A(2)…A(10). 陣列元素取用的增加值. 宣告陣列的範圍. 6-1 矩陣的宣告與使用. 陣列宣告 一維陣列宣告
E N D
設定陣列的大小,一定是整數 陣列變數的名字 所要使用的資料型態,可以是integer / real / …等等的基本型態外,還可以是自己用type所定義出來的自訂型態 A(1) A(2) A(3) A(10) … A 6-1 矩陣的宣告與使用 陣列宣告 integer :: A(10) 宣告10個元素的整數陣列A,其元素為A(1)、 A(2)…A(10)
陣列元素取用的增加值 宣告陣列的範圍 6-1 矩陣的宣告與使用 陣列宣告 一維陣列宣告 integer :: A(10)宣告10個元素的整數陣列A,其元素為A(1),A(2),…,A(10) integer :: A(-1:8)宣告10個元素的整數陣列A,其元素為A(-1), A(0), A(1), A(2),…,A(8) integer :: A(0:10:2)宣告6個整數元素陣列,其元素為A(0),A(2),A(4),A(6),A(8), A(10) integer :: A(0:10:2)宣告6個整數元素陣列,其元素為A(10),A(8),A(6),A(4),A(2),A(0)
6-1 矩陣的宣告與使用 陣列宣告 多維陣列宣告 integer :: A(3,3)宣告一個3×3的二維陣列 integer :: A(0:3,0:3)宣告一個4×4的二維矩陣 integer :: A(3,3,3)宣告一個3×3×3的三維陣列
括號和斜號之間不能有空白 a(2) a(4) a(1) a(3) a(5) a 1 2 3 4 5 6-2 設定陣列的初值 陣列初始化 integer :: a(5) = (/ 1, 2, 3, 4, 5 /) 代表a(1) = 1, a(2) = 2, a(3) = 3, a(4) = 4, a(5) = 5 integer :: a(5) = (/ (3, i = 1, 5) /)代表a(1) = a(2) = a(3) = a(4) = a(5) = 3
6-2 設定陣列的初值 陣列初始化 integer :: a(5) = (/( i, i = 1, 5) /)代表a(1) = 1, a(2) = 2, a(3) = 3, a(4) = 4, a(5) = 5 integer :: a(5) = (/ (3, i = 1, 5) /)代表a(1) = a(2) = a(3) = a(4) = a(5) = 3 integer :: a(5) = (/ 0, ( i, i = 2, 4 ), 5 /)代表a(1) = 0, a(2) = 2, a(3) = 3, a(4) = 4, a(5) = 5
A(2) A(4) A(1) A(3) A(5) A 6-3 陣列在電腦記憶體中的儲存方法 一維陣列儲存方法 integer :: A(5) 元素在記憶體的連續區塊中的排列情況為A(1)→A(2)→A(3)→A(4)→A(5) integer :: A(0:10:2)元素在記憶體的連續區塊中的排列情況為A(0)→A(2)→A(4)→A(6)→A(8)→A(10)
A A(1,1) A(1,2) A(1,3) ↓The first row A(2,1) A(2,2) A(2,3) 先放first column column major排列法 再放second column A(3,1) A(3,2) A(3,3) 其次third column ↑The first column A(1,1) A(2,1) A(3,1) A(1,2) A(2,2) A(3,2) A(1,3) A(2,3) A(3,3) A 6-3 陣列在電腦記憶體中的儲存方法 二維陣列儲存方法 integer :: A(3,3)陣列A在記憶體的排列情況為 A(1,1) → A(2,1) → A(3,1) → A(1,2) → A(2,2) → A(3,2) → A(1,3) → A(2,3) → A(3,3)
Not good,因為cpu要不斷的在記憶中跳躍式的來讀取資料,無法使用到快取記憶體(Cache)的便利 < Ex. 程式片段> 計算3X3陣列的和 sum=0 do i = 1, 3 do j = 1, 3 sum = sum + A(i,j) end do end do Cache會自動抓取鄰近近的記憶體資料到Cache中 A(1,1) A(2,1) A(3,1) A(1,2) A(2,2) A(3,2) A(1,3) A(2,3) A(3,3) A 6-3 陣列在電腦記憶體中的儲存方法 陣列儲存方法與程式
< Ex. 程式片段> 計算3X3陣列的和 sum=0 do i = 1, 3 do j = 1, 3 sum = sum + A(j,i) end do end do Better than before,充份利用cache,程式執行的速度會較快 A(1,1) A(2,1) A(3,1) A(1,2) A(2,2) A(3,2) A(1,3) A(2,3) A(3,3) A 6-3 陣列在電腦記憶體中的儲存方法 陣列儲存方法與程式
6-4 Fortran90新增有關矩陣的功能 整個矩陣的運作 • a = b將b陣列相對應的元素的值指定給a陣列 相當於 do i = 1, k (a,b,c皆為k個元素的一維陣列) a(i) = b(i) end do • a = b + c將b陣列與c陣列相對應的元素的值相加後指定給a陣列 相當於 do i = 1, k a(i) = b(i) + c(i) end do
6-4 Fortran90新增有關矩陣的功能 整個矩陣的運作 • a = b - c將b陣列與c陣列相對應的元素的值相減後指定給a陣列 相當於 do i = 1, k a(i) = b(i) – c(i) end do • a = b * c將b陣列與c陣列相對應的元素的值相加乘指定給a陣列 相當於 do i = 1, k a(i) = b(i) * c(i) end do
6-4 Fortran90新增有關矩陣的功能 整個矩陣的運作 • a = b / c將b陣列與c陣列相對應的元素的值相除後指定給a陣列 相當於 do i = 1, k a(i) = b(i) / c(i) end do • a(1:3) = b(4:6)b陣列指定特定元素的值給a陣列 相當於 a(1) = b(4), a(2) = b(5), a(3) = b(6)
6-4 Fortran90新增有關矩陣的功能 整個矩陣的運作 • a(1:5:2) = 3a陣列特定元素初始化 相當於 a(1) = 3, a(3) = 3, a(5) = 3 • a(1:10) = a(10:1:-1)把a(1~10)的內容給反轉 相當於 do i = 1, k/2 temp = a(i) a(i)=a(k+1-i) a(k+1-i)=temp end do
當logical_expr邏輯為真時,執行這一段程式 當logical_expr邏輯為假時,執行這一段程式 相當於程式的if 6-4 Fortran90新增有關矩陣的功能 Where where (logical_expr矩陣元素值的邏輯運算) …(矩陣運作) else where …(矩陣運作) end where
program ex0601 implicit none integer :: I real :: a(5) = (/ ( I, I = 5, 1, -1) /) real :: b(5) = (/ (I, I = 1, 5) /) real :: c(5) where ( a > b ) c = b else where c = a end where write (*,'(A10, 5F6.2)' ) 'Array C = ', ( c(I), I = 1, 5 ) stop end program ex0601 a(1)=5,a(2)=4,a(3)=3,a(4)=2,a(5)=1 < Ex. 完整程式> 相當於 do i = 1, k if ( a(i) > b(i) ) then c(i) = b(i) else c(i) = a(i) end if end do b(1)=1,b(2)=2,b(3)=3,b(4)=4,b(5)=5 < Ex. 執行結果> Array C = 1.00 2.00 3.00 2.00 1.00 6-4 Fortran90新增有關矩陣的功能 Where
6-4 Fortran90新增有關矩陣的功能 Forall (Fortran95所新增的功能) • forall ( i = 1:2, j = 1:2 ) a(i,j) = i + j 相當於 do j = 1, 2 do i = 1, 2 a(i,j) = i + j end do end do
如果forall中的敘述超過一行就要使用區塊的型式,最後還要加上end forall來做結束 6-4 Fortran90新增有關矩陣的功能 Forall • forall ( i = 1:2, j = 1:2 ) a(i,j) = i + j a(j,i) = i – jend forall 相當於 do j = 1, 2 do i = 1, 2 a(i,j) = i + j a(j,i) = i - j end do end do
6-4 Fortran90新增有關矩陣的功能 Forall • forall ( i = 1:10, j = 1:10, a(i,j) > 0 ) where ( a < 10 ) b = 10end forall 相當於 do j = 1, 10 do i = 1, 10 if ( a(i,j) > 0 ) then if ( a(i,j) < 10 ) then b(i,j) = 10 end if end if end do end do
只有一個冒號表示矩陣只有一個維度,要宣告兩個維度的矩陣則為A(:,:)只有一個冒號表示矩陣只有一個維度,要宣告兩個維度的矩陣則為A(:,:) 表示宣告矩陣是"可變大小"的矩陣 6-4 Fortran90新增有關矩陣的功能 可變大小的陣列 陣列可以等到程式執行中再來決定它所要使用的長度 可變大小陣列宣告 integer, allocatable :: A(:) ≡ integer, allocatable, dimension(:) :: A
設定矩陣大小為m其中m為整數變數 問電腦的記憶體要求空間來儲存資料 自定矩陣的上下限範圍m,n及增值量inc,其中m,n,inc皆為整數變數 6-4 Fortran90新增有關矩陣的功能 設定陣列的大小 可變大小的陣列宣告完成後,要先經由allocate這個敘述 來設定出陣列的大小後才能使用陣列 allocate(A(m)) allocate(A(m:n:inc))
要釋放的陣列名稱 將allocate所得到的陣列記憶體空間釋放 6-4 Fortran90新增有關矩陣的功能 釋放陣列空間 使用完陣列後,要先釋放陣列空間,才能重新設定陣列 大小 deallocate(A)
< Ex. 完整程式> program ex0603 implicit none integer :: students, i integer , allocatable :: grades( : ) write(*,*) 'How many students in this class A ?' read(*,*) students allocate(grades(students)) do i = 1, students write(*, '(1X, A25, I2, A2)') 'Input grades of number', I, ':' read(*,*) grades(i) end do 宣告一個可變動大小的一維陣列grades 設定陣列grades大小為students <接下頁> 6-4 Fortran90新增有關矩陣的功能 可變大小的陣列
< Ex. 完整程式> do i = 1, students if (grades(i) < 60) then write(*, '(1X, A10, I2, A8)') 'number', I, 'fail!' end if end do deallocate(grades) write(*,*) 'How many students in this class B ?' read(*,*) students allocate(grades(students)) 釋放陣列grades的空間以便重新使用 <接下頁> 6-4 Fortran90新增有關矩陣的功能 可變大小的陣列
< Ex. 完整程式> do i = 1, students write(*, '(1X, A25, I2, A2)') 'Input grades of number', I, ':' read(*,*) grades(i) end do do i = 1, students if (grades(i) < 60) then write(*, '(1X, A10, I2, A8)') 'number', I, 'fail!' end if end do stop end program ex0603 6-4 Fortran90新增有關矩陣的功能 可變大小的陣列
< Ex.執行結果> How many students in this class A ?3 <輸入 3 [ENTER] >Input grades of number 1 :99 <輸入 9 0 [ENTER] > Input grades of number 2 :70 <輸入 7 0 [ENTER] > Input grades of number 3 :58 <輸入 5 8 [ENTER] > number 3 fail!How many students in this class B ?2 <輸入 2 [ENTER] > Input grades of number 1 :59 <輸入 5 9 [ENTER] > Input grades of number 2 :45 <輸入 4 5 [ENTER] > number 1 fail! number 2 fail! 6-4 Fortran90新增有關矩陣的功能 可變大小的陣列
error是事先宣告好的整數變數,做allocate這個動作時會經由stat這個敘述傳給error一個數值。error等於0表示allocate陣列成功 error不等於0則表示電腦的記憶不足,allocate陣列失敗 6-4 Fortran90新增有關矩陣的功能 allocate,deallocate的確認 allocate,deallocate可以利用stat來確認是否執行成功 allocate(A(m), stat =error) deallocate(A(m), stat =error)
6-4 Fortran90新增有關矩陣的功能 陣列的庫存函數 • dot_product(vector_a, vector_b) 將兩同維度的向量vector_a與vector_b做內積(dot product)運算 • matmul(matrix_A, matrix_B) 將兩矩陣matrix_A與matrix_B做乘法以適當的陣列顯示 • maxloc(array, mask) <=> minloc(array, mask) 在滿足mask的條件下,找出陣列中最大值/最小值的所在位置,傳 回一個整數。 mask的運算方法和陣列在where中所使用的邏輯運算一樣。 Ex. b=maxloc(a,a<50)找出陣列中小於50的最大數值的所在位置
Ex. integer :: a(3,3) = reshape( (/1,2,3,4,5,6,7,8,9/), (/3,3/)) Ex. integer :: b(2,3) = reshape( (/1,2,3,4,5,6/), (/2,3/)) 6-4 Fortran90新增有關矩陣的功能 陣列的庫存函數 • maxval(array, mask)<=> minval(array, mask) 在滿足mask的條件下,找出陣列中最大值/最小值,傳回最大值/ 最小值 • reshape(data_source, shape) 把資料“整型”好後,再傳給一個陣列,常用在設定陣列初值時使 用
6-4 Fortran90新增有關矩陣的功能 陣列的庫存函數 • sum(array, mask) 在滿足mask的條件下,計算陣列元素的和。若沒有mask,則表 示計算陣列所有元素的和。 • transpose(matrix) 傳回轉置後的陣列