FORTRAN是英文“FORmula TRANslator”的縮寫,譯為“公式翻譯器”,它是世界上最早出現的計算機高級程序設計語言,廣泛應用於科學和工程計算領域。FORTRAN語言以其特有的功能在數值、科學和工程計算領域發揮着重要作用。
早在1951年,美國IBM公司約翰·貝克斯(John Backus)針對匯編語言的缺點着手研究開發FORTRAN語言,並於1954年在紐約正式對外發布。稱約翰·貝克斯提出的FORTRAN語言為FORTRANⅠ,FORTRANⅠ雖然功能簡單,但它的開創性工作,在社會上引起了極大的反響。到1957年第一個FORTRAN編譯器在IBM704計算機上實現,並首次成功運行了FORTRAN程序。
在1958年,對FORTRANⅠ進行了擴充和完善,引進了子函數等概念,推出了商業化的FORTRANⅡ版本。之后,FORTRAN語言發展迅速,多種版本相繼在其它計算機上實現。
符:Fortran不區分大小寫
Fortran 格式:自由格式和固定格式。Fortran程序代碼擴展名為:*.For 或*.F的文件就是指固定格式;以*.F90為擴展名的文件,就是自由格式。
à固定格式:規定了程序代碼每一行中每個字段的意義。第7~72個字符,是可以用來編寫程序的字段。每一行的前5個字符只能是空格或數字,數字用來作為“行代碼”。每一行的第6個字符只能是空格或“0”以外的字符。
第1個字符 |
如果是C、c或者星號*,這行文本會被當成說明批注,不會被編譯 |
第1~5個字符 |
如果是數字,就是用來給這一行程序代碼取個代號。不然只能是空格 |
第6個字符 |
如果是“0”以外的任何字符,表示這一行程序會接續上一行 |
第7~72個字符 |
Fortran程序代碼的編寫區域 |
第73個字符之后 |
不使用,超過的部分會被忽略,有的編譯器會發出錯誤信息 |
à自由格式:嘆號(!)后面的文本都是注釋。 每行可以編寫132個字符。行號放在每行程序的最前面。 一行程序代碼的最后如果是符號&,代表下一行程序會和這一行連接;如果一行程序代碼的開頭是符號&,代表它會和上一行程序連接。
Fortran的數據類型
à整型(Integer) à浮點數(Real) à復數(Complex) à字符(Character)
à邏輯判斷(Logical)—True or False
Remark: Visual Fortran安裝好后,默認的安裝目錄C:\Program Files\Microsoft Visual Studio\DV98\bin下有一個Bitviewer程序可以用來表看各種數據格式實際在內存中的二進制數據。
Fortran的數學表達式
()(括號)、**(乘冪)、*(乘法)or /(除法)、+(加法) or –(減法)à優先級(高à低).
輸入(Write)輸出(Print)命令
Fortran程序通常以Program描述來開頭,Program后面還要接一個自定義的程序名稱(這個名稱可以完全自定義,不需要和文件名有任何關系)。Fortran程序最后還要有End描述,表示程序代碼寫到這一行結束。
Write(*,*)命令:括號中的兩個星號都有各自的意義,第一個星號代表輸出的位置使用默認值,也就是屏幕,第二個星號則代表不特別設置輸出格式。
終歸一句話,Write這個命令的最簡單用法,就是在括號中掛上兩個星號,再把所要輸出的字符串用兩個雙引號引起來放在后面。
E.g.:write (*,*) “Hello, Acuzio!” à 完整的寫法 write(Unit = *, FMT=*) “Hello, Acuzio!”
Write命令注意:
l 每一次執行Write命令后,會自動切換到下一行來准備做下一次的輸入
l 因為雙引號是用來“輸出”字符串的,所以想要輸出雙引號時,要連用兩個雙引號。
l Fortran90可以使用雙引號或單引號來封裝字符串,Fortran77標准中只能使用單引號,不過大部分的Fortran77編譯器還是可以接受雙引號。
STOP命令:是終止程序的意思,它可以出現在程序的任何地方,程序執行到這個命令就會中止。除非必要,不要把Stop命令使用在主程序結束之外的其他地方。因為一個程序,如果有太多的終止點會容易出錯。
把上面例子中用Print命令,程序執行的結果是一樣的àPrint *, ”Hello, Acuzio!”
Print的用法和write大致上相同,只是print后面不使用括號,而且只有一個星號。這個星號的意義是不限定輸出格式。Print和Write的不同處就在於少了Write的第一個星號,也就是少了賦值輸出位置的能力,Print命令只能針對屏幕來使用。建議盡量使用Write來做輸出的工作,因為如果日后想把程序的輸出轉換到其他地方,例如轉換到文件中,使用Write命令的程序改寫起來比較容易,只有把UNIT值指到另一個輸出位置就行了。
Integer:Integer(kind = 4) a Integer *4 a Integer(4) a
其中kind=4、*4、(4)都是賦值要使用4個bytes來存放整數的意思。
聲明變量的原則:
l 變量的名稱以使用英文字母為原則,可以內含下划線或數字,但前綴必須是英文字母
l 變量名字的長度,在77標准中最起碼支持6個字符長,90標准中最起碼支持31個字符長。也就是說在Fortran77中變量長度最后是在1~6之間,在Fortran90中變量長度則最后是在1~31之間
l 變量名稱最好不要和Fortran的執行命令同名,也不能和主程序的名稱或是前面聲明過的變量同名。
l 程序中辨認變量時,不會區分它的大小寫
Fortran90的聲明語法多了一些變化,它可以在類型的后面先寫兩個冒號“::”,再寫上變量的名稱
Real:
Real(kind=4)表示單精度。Real(kind=8)表示雙精度
Complex:
Fortran中聲明復數的方法:Complex a
復數是有實部和虛部兩個部分組成,而Fortran中保存這兩個數字的方法是用兩個浮點數來保存,所有復數也可以分成單精度及雙精度兩種類型。
要設置一個復數數值的方法如下:a=(x,y) !x為實部,y為虛部,當a=(3.2,2.5)時,表示a=3.2+2.5i
Character:
聲明:character(len=10) a character(10)a character*10 a character*(10) a
字符串長度需要多少字符,就賦值多少數字給它
Program ex Character(len=20) string String = “Good morning.” Write(*,*) string String(6) = “evening.” !重新設置從第六個字符之后的字符串 Write(*,*) string end |
上例中 string(1:2) = “GO” !字符串最前面兩個字符會變成GO
String(13:13)=”!” !字符串的第13個字符會變成嘆號
用(//)可以把前后兩個字符串連接起來
Fortran有關字符串運行的函數
Char(num) |
返回計算機所使用的字符表上,數值num所代表的字符 |
IChar(char) |
返回所輸入的char字符在計算機所使用的字符表中所代表的編號,返回值是整數類型 |
Len(string) |
返回輸入字符串的聲明長度,返回值是整數類型 |
Len_Trim(String) |
返回字符串去除尾端空格后的實際內容長度 |
Index(string,key) |
所輸入的String和key都是字符串。這個函數會返回key這個“子字符串”在“母字符串”String中第一次出現的位置 |
Trim(string) |
返回把string字符串尾端多余空格清除過后的字符串 |
Logical:
邏輯變量並賦值。Logical a = .true.
設置邏輯變量的方法:當設置“真”值或者“假”值,請注意要在true和false的前后要加上兩個點
輸入命令Read
Read(*,*) read命令在使用時和write一樣,都有兩個星號。代表的意義也是差不多的,第一個星號代表輸入的來源使用默認的設備(也就是鍵盤),第二個星號代表不指定輸入格式
格式化輸入輸出(Format)
Program ex Integer a a = 100 write(*,100) a !使用行代碼100,也就是第五行的格式來輸出變量a 100 format(I4) !最前面的100是行代碼,把這一行程序代碼給一個編號 End |
Format格式
Aw |
以w個字符寬來輸出字符串 |
BN |
定義文本框中的空位為沒有東西,在輸入時才需要使用 |
BZ |
定義文本框中的空位代表0,在輸入時才需要使用 |
Dw.d |
以w個字符寬來輸出指數類型的浮點數,小數部分占d個字符寬 |
Ew.d[Ee] |
以w個字符寬來輸出指數類型的浮點數,小數部分占d個字符寬,指數部分占e個字符 |
ENw.d[Ee] |
以指數類型來輸出浮點數 |
ESw.d[Ee] |
以指數類型來輸出浮點數 |
Fw.d |
以w個字符寬來輸出浮點數,小數部分占d個字符寬 |
Gw.d[Ee] |
以w個字符寬來輸出整數,最少輸出m個數字 |
Iw[.m] |
以w個字符寬來輸出整數,最少輸出m個數字 |
Lw |
以w個字符寬來輸出T或F的真假值 |
nX |
把輸出的位置向右跳過n個位置 |
/ |
代表換行 |
: |
在沒有更多數據時結束輸出 |
kP |
K值控制輸入輸出的SCALE |
Tn |
輸出的位置移動到本行第n列 |
TLn |
輸出的位置向左相對移動n列 |
TRn |
輸出的位置向右相對移動n列 |
SP |
在數值為正時加上“正號” |
SS |
取消SP |
Fortran 90添加的格式 |
|
Bw[.m] |
把整數轉換成二進制來輸出、輸出會占w個字符寬,固定輸出m個數字。m值可以不給定 |
Ow[.m] |
把整數轉換成八進制來輸出,輸出會占w個字符寬,固定輸出m個數字。m值可以不給定 |
Zw[.m] |
把整數轉換成十六進制來輸出,輸出會占w個字符寬,固定輸出m個數字。m值可以不給定 |
變量名稱的取名策略:變量的名字中可以使用的字符集包括英文的26個字母、0~9這10個數字以及下划線“_”,不過前綴必須是英文字母。變量名稱的長度限制隨着各家編譯器的不同而不同,Fortran 標准規定最少要支持到6個字符,Fortran90則最少要支持到31個字符
Implicit
Fortran 標准中有一項不太好的功能,它的變量不一定要經過程序聲明才能使用,編譯器會根據變量的第一個字母來自東決定這個變量的類型。第一個字母為I、J、K、L、M、N的變量會被視為整數類型,其他的變量則會被當成浮點數來使用。
Implicit命令的功能是用來設置“默認類型”。所謂的默認類型,是指Fortran不經過聲明,由第一個字母來決定變量類型。可以經過Implicit描述來決定哪些字母開頭的變量會自動使用某種類型
Implicit integer (A,B,C) !A、B、C開頭的都被視為整型數 Implicit integer(A-F,I,K) !A到F及I、K開頭的變量都視為整型數 Implicit real(M-P) !M到P開頭的變量都視為浮點數 Implicit none !關閉默認類型功能,所有變量都要事先聲明 |
常數的聲明方法(Parameter)
Program ex Implicit none Real ::pi Parameter(pi = 3.14129) Write(*,”(F4.2)”) sin(pi/6) end |
在Fortran90里,Parameter可以作為形容詞,和變量的聲明同時寫在一起
Real, parameter ::pi=3.14159 !這里pi前面的冒號不能省,和上面代碼不同(上面的可以省略)
設置變量的初值
變量內容並不一定要在程序執行時才設置,可以在聲明時同時給予初值。在Fortran90偶那個,在設置變量初值時,直接把數值寫在聲明的變量后面就行了。使用這個方法來設置初值是,不能省略聲明中間的那兩個冒號(Fortran90)
在fortran77中則要使用Data命令設置初值
Fortran 90 |
Fortran 77 |
program ex90 implicit none integer ::a=1 real ::b=2.0 complex ::c=(1.0,2.0) character (len=20) ::str="Hello Acuzio!" write (*,*) a,b,c,str end |
program ex77 implicit none integer a real b complex c character (len=20) str data a,b,c,str/1,2.0,(1.0,2.0),’Hello ‘/ write (*,*) a,b,c,str end |
等價聲明(equivalence)
把兩個以上的變量,聲明它們使用同一個內存地址,就是“等價聲明”。使用同一個內存位置的變量,只要改變其中一個變量,就會同時改變其他變量的數值
Integer a,b Equivalence(a,b) |
Fortran 90 的自定義數據類型
使用關鍵字:type
Type ::person Character(len=30) ::name Integer ::age Integer ::length Integer ::weight End type person |
Type(person) ::a !聲明一個person類型的變量 a%name !引用person中的name |
Kind的使用
Kind描述如果搭配上一些Fortran90的庫函數,可以增加程序代碼的“跨平台”能力
Fortran 90提供庫函數來判斷所要記錄的數值值域范圍所需要的kind值
Selected_int_kind(n) : 返回如果想要記錄n位整數時,所應聲明的kind.返回-1時,表示無法提供所想要的值域范圍
Selected_real_kind(n,e) : 返回如果想要能夠記錄具有N位有效位數、指數達到e位的浮點數所需要的kind值。返回-1表示無法滿足所要求的有效位數、返回-2表示無法滿足所要求的指數范圍、返回-3表示兩者都無法滿足
IF基本用法
If(邏輯判斷式) then …… End if |
If(邏輯判斷式) then …… Else …… End if |
邏輯運算符:
Fortran 90 |
|
Fortran 77 |
||
== |
判斷是否“相等” |
|
.eq. |
判斷是否“等於” |
/= |
判斷是否“不相等” |
|
.ne. |
判斷是否“不等於” |
> |
判斷是否“大於” |
|
.gt. |
判斷是否“大於” |
>= |
判斷是否“大於或等於” |
|
.ge. |
判斷是否“大於或等於” |
< |
判斷是否“小於” |
|
.lt. |
判斷是否“小於” |
<= |
判斷是否“小於或等於” |
|
.le. |
判斷是否“小於或等於” |
邏輯判斷式
.and. |
交集,如果兩邊的表達式都成立,整個表達式就成立 |
.or. |
並集,兩邊的表達式只要有一個成立,整個表達式就成立 |
.not. |
邏輯反向,如果后面的表達式不成立,整個表達式就成立 |
.eqv. |
兩邊表達式的邏輯運算結果相同時,整個表達式就成立 |
.neqv. |
兩邊表達式的邏輯運算結果不同時,整個表達式就成立 |
多重判斷
If(條件1) then …… Else if(條件2) then Else …… End if |
浮點數及字符的邏輯運算
使用浮點數來做邏輯運算時,要避免使用“等於”的判斷。因為使用浮點數做計算時,有效位數是有限的,難免會出現計算上的誤差,理想中的等號不一定會成立。要使用浮點數來做“等於”的邏輯判斷時,最好用其他方法來取代(ABS這個函數是取絕對值。使用誤差小於某一個值來進行判斷)
Select case語句
Select case(變量) Case(數值) …… Case(數值2) …… Case default …… End select |
在case里的冒號前后放兩個數值時,代表在這兩個數值范圍中的所有數值
Remark:
l Select case只能使用整數(integer)、字符(character)及邏輯變量(logical),不能使用浮點數及復數
l 每個case中所使用的數值必須是固定的常量,不能使用變量
Pause, continue, stop
Pause的功能就跟它的字母意義相同,程序執行到pause時,會暫停執行,直到用戶按下enter鍵才會繼續執行。
Continue 無實際用途
Stop 結束程序執行
Fortran 90的庫中,IAND用來做二進制的AND計算,IOR用來做二進制的OR計算
DO循環
Integer, parameter ::index = 1 Integer, parameter ::counts = 100 Do index,counts,1 …… End do |
Real,parameter ::weight =45.0 !答案 Real,parameter ::e=0.001 !誤差 Real ::guess Do while(abs(guess-weight)>e) Write(*,*) “Weight” Read(*,*) guess End do |
循環控制:
Cycle和exit
Cycle 命令可以略過循環的程序模塊中,在cycle命令后面的所有程序代碼,直接跳回循環的開頭來進行下一次循環
Exit 功能:可以直接“跳出”一個正在運行的循環
署名循環
循環還可以取“名字”,這個用途是可以在編寫循環是能明白地直到End do這個描述的位置是否正確,尤其是在多層循環當中。署名的循環也可以配合Cycle、exit來使用。
數組(Array)
數組的聲明方法:Datatype name(size)
賦初值:
integer A(5) Data a /1,2,3,4,5/ |
Integer a(5) Data a /5*3/ !5個3 |
Integer A(5) Integer i Data(A(i),i=2,4) /2,3,4/ !這是一個隱含式循環,I會從2增加到4,依照順序到后面取數字。初值設定結果為A(2)=2、A(3)=3、A(4)=4,A(1)和A(5)沒有設定 |
Fortran 90隱含式循環的功能可以更強大
Integer ::a(5)=(/(I,I=1,5)/) !設置結果:a(1)=1,a(2)=2,a(3)=3,a(4)=4,a(5)=5
Where
Where是Fortran95添加的功能,它也是用來取出部分數組內容進行設置
Forall
Forall是fortran95添加的功能。間斷地說,它也可以看出是一種使用隱含循環來使用數組的方法,不過它的功能可以做得更強大。
Integer i Integer ::a(5) Forall(i=1:5) A(1)=5 End forall |
Forall詳細語法為
Forall(triplet1[,triplet2[,triplet3……]],mask)
……
End forall
其中mask用來做條件判斷
Fortran90 可以聲明可變大小數組
Integer,allocatable ::a(:) !聲明一個可變大小的一位數組 Integer ::students Read(*,*) students Allocate(a(students)) !配置內存空間 |
計算機的內存是有限的,當然也就不能無限制地去要求空間來使用。所以allocate命令在內存滿載是,有可能會要求不到使用空間。Allocate命令中可以加上stat的文本框得知內存配置是否成功
Allocate(a(100),stat=err) !err是事先聲明號的整型變量,做allocate這個動作時會經有stat這個敘述傳給err一個數值,如果err等於0則表示allocate數組成功,而如果err不等於0
則表示allocate數組失敗
Deallocate(a) 表示刪除分配的內存
跟allocate相關的函數還有allocated,它用來檢查一個可變大小的矩陣是否已經配置內存使用,他會返回一個邏輯值
If(.not. allocated(a))then Allocate(a(5)) End if |
函數
子程序(subroutine)的使用
子程序代碼以subroutine開頭,它同樣要取一個名字,以end或end subroutine來結束。嚴格地講,end subroutine后還可以再接上這個子程序的名字
program ex implicit none integer ::a=1 integer ::b=2 call add(a,b) end
subroutine add(first,second) implicit none integer ::first,second write(*,*) first+second return end |
函數的調用
program ex implicit none real ::a=5,b=4 real,external ::add !聲明add是函數而不是變量 !調用函數add,調用函數不必使用call命令 write(*,*) add(a,b) end
function add(a,b) implicit none real ::a,b real ::add add =a+b return end |
全局變量
Common是fortran77使用“全局變量”的方法,它用來定義一塊共享的內存空間
program ex implicit none integer ::a,b common a,b !定義a,b是全局變量中的第1及第2個變量 a=1 b=2 call showCommon() end
subroutine showCommon() implicit none integer ::num1,num2 common num1,num2 !定義num1,num2是全局變量中的第1及第2個變量 write(*,*) num1,num2 return end |
Block data
關於common還有最后要介紹的就是設置初值的方法,common變量不能直接在子程序或主程序中使用data來設置初值,要在block data程序模塊中使用data命令來設置初值
program ex implicit none integer ::a,b common a,b !a,b放在不署名的全局變量空間中 integer ::c,d common /group1/c,d !c,d放在group1的全局變量空間中 integer ::e,f common /group2/e,f !e,f放在group2的全局變量空間中
write (*,"(6I4)") a,b,c,d,e,f end
block data implicit none integer a,b common a,b !a,b放在不署名的全局變量空間中 data a,b /1,2/ !設置a,b的初值 integer c,d common /group1/c,d !c,d放在group1的全局變量空間中 data c,d /3,4/ !設置c,d的初值 integer e,f common /group2/e,f !e,f放在group2的全局變量空間中 data e,f /5,6/ !設置e,f的初值 end block data |
變量的生命周期
在聲明中加入save 可以拯救這些變量、增加變量的生命周期、保留住所保存的數據。這些變量可以在程序執行中永久記憶住上一次函數調用時所被設置的數值
program ex implicit none call sub() call sub() call sub() end
subroutine sub() implicit none integer ::count = 1 save count !賦值count變量會永遠活着,不會忘記它的內容 write(*,*) count count = count + 1 return end |
在Fortran 90 中,可以把save跟聲明寫作同一行
Integer ,save ::count=1
傳遞函數
傳遞參數時,除了傳遞數字、字符等等數據之外,還可以把一個函數名稱當成參數傳送出去
program ex implicit none real,external ::func !聲明func是個自定義函數 real,intrinsic ::sin !聲明sin是庫函數
call ExecFunc(func) !輸入自定義函數func call ExecFunc(sin) !輸入庫函數sin end
subroutine ExecFunc(f) implicit none real,external ::f !聲明參數f是個函數 write(*,*) f(1.0) !執行輸入函數f return end
real function func(num) implicit none real ::num func = num*2 return end |
關鍵字Intrinsic表明所聲明的sin是fortran的庫存函數,而不是一個變量