【转载】Fortran - 快速指南

目录

Fortran - 快速指南

转载自https://iowiki.com/fortran/,在此基础上做了一些补充。

Fortran - Overview

Fortran,源自公式翻译系统,是一种通用的命令式编程语言。 它用于数字和科学计算。

Fortran最初由IBM在20世纪50年代开发用于科学和工程应用。 Fortran统治了这个编程领域很长一段时间,并且因为高性能计算而变得非常流行。

它支持 -

  • 数值分析与科学计算
  • 结构化编程
  • 数组编程
  • 模块化编程
  • 通用编程
  • 超级计算机上的高性能计算
  • 面向对象编程
  • 并发编程
  • 计算机系统之间的合理程度的可移植性

关于Fortran的事实

  • Fortran由IBM的John Backus于1957年领导的团队创建。
  • 最初这个名称曾用全部资本编写,但目前的标准和实施只要求第一个字母为资本。
  • Fortran代表FORmula TRANslator。
  • 最初是为科学计算而开发的,它对字符串和通用编程所需的其他结构的支持非常有限。
  • 后来的扩展和开发使其成为一种具有良好可移植性的高级编程语言。
  • 原始版本,Fortran I,II和III现在已被淘汰。
  • 仍在使用的最旧版本是Fortran IV和Fortran 66。
  • 今天最常用的版本是:Fortran 77,Fortran 90和Fortran 95。
  • Fortran 77添加了字符串作为一种独特的类型。
  • Fortran 90增加了各种线程和直接阵列处理。

Fortran - Environment Setup

在Windows中设置Fortran

G95是GNU Fortran多架构编译器,用于在Windows中设置Fortran。 Windows版本在Windows下使用MingW模拟unix环境。 安装程序会处理此问题并自动将g95添加到Windows PATH变量中。

你可以从here获得稳定版的G95

如何使用G95

在安装过程中,如果选择“RECOMMENDED”选项, g95将自动添加到PATH变量中。 这意味着您只需打开一个新的命令提示符窗口并键入“g95”即可打开编译器。 找到下面的一些基本命令来帮助您入门。

Sr.No 命令和描述
1 g95 –c hello.f90将hello.f90编译为名为hello.o的目标文件
2 g95 hello.f90编译hello.f90并将其链接以生成可执行文件a.out
3 g95 -c h1.f90 h2.f90 h3.f90编译多个源文件。 如果一切顺利,则创建对象文件h1.o,h2.o和h3.o
4 g95 -o hello h1.f90 h2.f90 h3.f90编译多个源文件并将它们链接到一个名为'hello'的可执行文件

G95的命令行选项

-c Compile only, do not run the linker.
-o Specify the name of the output file, either an object file or the executable.

可以一次指定多个源文件和目标文件。 Fortran文件由以“.f”,“.F”,“。for”,“.FOR”,“。f90”,“.F90”,“。f95”,“.F95”,“。”结尾的名称表示。 f03“和”.F03“。 可以指定多个源文件。 也可以指定目标文件,并将其链接以形成可执行文件。

在linux中设置Fortran

这里使用ubuntu,安装如下:

sudo apt install  gfortran-10

Fortran - Basic Syntax

Fortran程序由一组程序单元组成,如主程序,模块和外部子程序或过程。

每个程序包含一个主程序,可能包含也可能不包含其他程序单元。 主程序的语法如下 -

program program_name
implicit none      
! type declaration statements      
! executable statements  
end program program_name

Fortran中的一个简单程序

让我们编写一个程序,添加两个数字并打印结果 -

program addNumbers
! This simple program adds two numbers
   implicit none
! Type declarations
   real :: a, b, result
! Executable statements
   a = 12.0
   b = 15.0
   result = a + b
   print *, 'The total is ', result
end program addNumbers

编译并执行上述程序时,会产生以下结果 -

The total is 27.0000000    

请注意 -

  • 所有Fortran程序都以关键字program开头,以关键字end program,后跟end program,名称。
  • implicit none语句允许编译器检查是否正确声明了所有变量类型。 您必须始终在每个程序的开头使用implicit none
  • Fortran中的注释以感叹号(!)开头,因为编译器会忽略此后的所有字符(字符串除外)。
  • print *命令在屏幕上显示数据。
  • 压缩代码行是保持程序可读性的好方法。
  • Fortran允许使用大写和小写字母。 除字符串文字外,Fortran不区分大小写。

Basics

Fortran的basic character set包含 -

  • 字母A ... Z和a ... z
  • 数字0 ... 9
  • 下划线(_)字符
  • 特殊字符=:+空白 - * /()[] ,. $'! “%&; <>?

Tokens由基本字符集中的字符组成。 令牌可以是关键字,标识符,常量,字符串文字或符号。

程序语句由令牌组成。

识别 Identifier

标识符是用于标识变量,过程或任何其他用户定义项的名称。 Fortran中的名称必须遵循以下规则 -

  • 它不能超过31个字符。
  • 它必须由字母数字字符(字母表中的所有字母,数字0到9)和下划线(_)组成。
  • 名称的第一个字符必须是字母。
  • 名称不区分大小写

关键字 (Keywords)

关键字是为语言保留的特殊单词。 这些保留字不能用作标识符或名称。

下表列出了Fortran关键字 -

非I/O关键字
allocatable allocate assign assignment 阻止数据
call case character common complex
contains continue cycle data deallocate
default do 双精度 else 否则如果
elsewhere 结束块数据 结束了 结束功能 万一
结束界面 结束模块 结束计划 结束选择 结束子程序
结束类型 结束在哪里 entry equivalence exit
external function if implicit
in inout integer intent interface
intrinsic kind len logical module
namelist nullify only operator optional
out parameter pause pointer private
program public real recursive result
return save 选择案例 stop subroutine
target then type type() use
Where While
与I/O相关的关键字
backspace close endfile format inquire
open print read rewind Write

Fortran - Data Types

Fortran提供了五种内部数据类型,但是,您也可以派生自己的数据类型。 五种内在类型是 -

  • 整数类型
  • 真实的类型
  • 复杂类型
  • 逻辑类型
  • 字符类型

整数类型

整数类型只能包含整数值。 以下示例提取可以保存在通常的四字节整数中的最大值 -

program testingInt
implicit none
   integer :: largeval
   print *, huge(largeval)
end program testingInt

编译并执行上述程序时,会产生以下结果 -

2147483647

请注意, huge()函数给出了特定整数数据类型可以保存的最大数字。 您还可以使用kind说明符指定字节数。 以下示例演示了这一点 -

program testingInt
implicit none
   !two byte integer
   integer(kind = 2) :: shortval
   !four byte integer
   integer(kind = 4) :: longval
   !eight byte integer
   integer(kind = 8) :: verylongval
   !sixteen byte integer
   integer(kind = 16) :: veryverylongval
   !default integer 
   integer :: defval
   print *, huge(shortval)
   print *, huge(longval)
   print *, huge(verylongval)
   print *, huge(veryverylongval)
   print *, huge(defval)
end program testingInt

编译并执行上述程序时,会产生以下结果 -

32767
2147483647
9223372036854775807
170141183460469231731687303715884105727
2147483647

真实的类型

它存储浮点数,例如2.0,3.1415,-100.876等。

传统上有两种不同的实际类型,默认的real类型和double precision类型。

但是,Fortran 90/95通过kind说明符提供了对实数和整数数据类型精度的更多控制,我们将在有关数字的章节中进行研究。

以下示例显示了实际数据类型的使用 -

program division   
implicit none  
   ! Define real variables   
   real :: p, q, realRes 
   ! Define integer variables  
   integer :: i, j, intRes  
   ! Assigning  values   
   p = 2.0 
   q = 3.0    
   i = 2 
   j = 3  
   ! floating point division
   realRes = p/q  
   intRes = i/j
   print *, realRes
   print *, intRes
end program division  

编译并执行上述程序时,会产生以下结果 -

0.666666687    
0

复杂类型

这用于存储复数。 复数有两部分,实部和虚部。 两个连续的数字存储单元存储这两个部分。

例如,复数(3.0,-5.0)等于3.0 - 5.0i

我们将在Numbers章节中更详细地讨论复杂类型。

逻辑类型

只有两个逻辑值: .true..false.

字符类型

字符类型存储字符和字符串。 字符串的长度可以由len说明符指定。 如果未指定长度,则为1。

For example,

character (len = 40) :: name  
name = “Zara Ali”

表达式name(1:4)将给出子串“Zara”。

隐式打字

较旧版本的Fortran允许一种称为隐式类型的功能,即您不必在使用前声明变量。 如果未声明变量,则其名称的第一个字母将确定其类型。

以i,j,k,l,m或n开头的变量名称被认为是整数变量,其他变量是实变量。 但是,您必须声明所有变量,因为它是良好的编程习惯。 为此你用声明开始你的程序 -

implicit none

此语句将关闭隐式类型。

Fortran - Variables

变量只不过是我们的程序可以操作的存储区域的名称。 每个变量都应该有一个特定的类型,它决定了变量内存的大小和布局; 可存储在该内存中的值范围; 以及可以应用于变量的操作集。

变量的名称可以由字母,数字和下划线字符组成。 Fortran中的名称必须遵循以下规则 -

  • 它不能超过31个字符。
  • 它必须由字母数字字符(字母表中的所有字母,数字0到9)和下划线(_)组成。
  • 名称的第一个字符必须是字母。
  • 名称不区分大小写。

基于前一章中解释的基本类型,以下是变量类型 -

Sr.No 类型和描述
1 Integer它只能包含整数值。
2 Real它存储浮点数。
3 Complex它用于存储复数。
4 Logical它存储逻辑布尔值。
5 Character它存储字符或字符串。

变量声明 (Variable Declaration)

变量在类型声明语句中的程序(或子程序)的开头声明。

变量声明的语法如下 -

type-specifier :: variable_name

例如 (For example)

integer :: total  	
real :: average 
complex :: cx  
logical :: done 
character(len = 80) :: message ! a string of 80 characters

稍后您可以为这些变量赋值,例如,

total = 20000  
average = 1666.67   
done = .true.   
message = “A big Hello from IOWIKI” 
cx = (3.0, 5.0) ! cx = 3.0 + 5.0i

您还可以使用内部函数cmplx,将值赋给复杂变量 -

cx = cmplx (1.0/2.0, -7.0) ! cx = 0.5 – 7.0i 
cx = cmplx (x, y) ! cx = x + yi
123

例子 (Example)

以下示例演示了屏幕上的变量声明,分配和显示 -

program variableTesting
implicit none
   ! declaring variables
   integer :: total      
   real :: average 
   complex :: cx  
   logical :: done 
   character(len=80) :: message ! a string of 80 characters
   !assigning values
   total = 20000  
   average = 1666.67   
   done = .true.   
   message = "A big Hello from IOWIKI" 
   cx = (3.0, 5.0) ! cx = 3.0 + 5.0i
   Print *, total
   Print *, average
   Print *, cx
   Print *, done
   Print *, message
end program variableTesting

编译并执行上述代码时,会产生以下结果 -

20000
1666.67004    
(3.00000000, 5.00000000 )
T
A big Hello from IOWIKI         

Fortran - Constants

常量是指程序在执行期间无法更改的固定值。 这些固定值也称为literals

常量可以是任何基本数据类型,如整数常量,浮点常量,字符常量,复数常量或字符串文字。 只有两个逻辑常量: .true..false.

常量被视为常规变量,除了它们的值在定义后无法修改。

命名常量和文字

常量有两种类型 -

  • 文字常数
  • 命名常量

文字常量具有值,但没有名称。

例如,以下是文字常量 -

类型
整数常量 0 1 -1 300 123456789
实常数 0.0 1.0 -1.0 123.456 7.1E + 10 -52.715E-30
复数常数 (0.0,0.0)( - 123.456E + 30,987.654E-29)
逻辑常数 。真正。 。假。
字符常量 “PQR”“a”“123'abc $%#@!”“引用”“”'PQR''''123“abc $%#@!''撇号'''

命名常量具有值和名称。

命名常量应在程序或过程的开头声明,就像变量类型声明一样,指示其名称和类型。 使用parameter属性声明命名常量。 例如,

real, parameter :: pi = 3.1415927

例子 (Example)

以下程序计算重力作用下垂直运动引起的位移。

program gravitationalDisp
! this program calculates vertical motion under gravity 
implicit none  
   ! gravitational acceleration
   real, parameter :: g = 9.81   
   ! variable declaration
   real :: s ! displacement   
   real :: t ! time  
   real :: u ! initial speed  
   ! assigning values 
   t = 5.0   
   u = 50  
   ! displacement   
   s = u * t - g * (t**2)/2  
   ! output 
   print *, "Time = ", t
   print *, 'Displacement = ',s  
end program gravitationalDisp

编译并执行上述代码时,会产生以下结果 -

Time = 5.00000000    
Displacement = 127.374992    

Fortran - Operators

运算符是一个符号,告诉编译器执行特定的数学或逻辑操作。 Fortran提供以下类型的运算符 -

  • 算术运算符
  • 关系运算符
  • 逻辑运算符

让我们一个一个地看看所有这些类型的运算符。

算术运算符 (Arithmetic Operators)

下表显示了Fortran支持的所有算术运算符。 假设变量A保持5,变量B保持3然后 -

显示示例

操作者 描述
+ 加法运算符,添加两个操作数。 A + B将给出8
- 减法运算符,从第一个减去第二个操作数。 A - B将给2
* 乘法运算符,将两个操作数相乘。 A * B将给出15
/ 除法运算符,用除分子除分子。 A/B将给1
** 指数运算符,将一个操作数提升到另一个操作数。 A ** B将给出125

关系运算符 (Relational Operators)

下表显示了Fortran支持的所有关系运算符。 假设变量A保持10,变量B保持20,则 -

显示示例

操作者 当量 描述
== .eq. 检查两个操作数的值是否相等,如果是,则条件变为真。 (A == B)不是真的。
/= .ne. 检查两个操作数的值是否相等,如果值不相等则条件变为真。 (A!= B)是真的。
> .gt. 检查左操作数的值是否大于右操作数的值,如果是,则条件变为真。 (A> B)不是真的。
< .lt. 检查左操作数的值是否小于右操作数的值,如果是,则条件变为真。 (A < B) 为真
>= .ge. 检查左操作数的值是否大于或等于右操作数的值,如果是,则条件变为真。 (A> = B)不是真的。
<= .le. 检查左操作数的值是否小于或等于右操作数的值,如果是,则条件变为真。 (A <= B)是真的。

逻辑运算符 (Logical Operators)

Fortran中的逻辑运算符仅适用于逻辑值.true。 和.false。

下表显示了Fortran支持的所有逻辑运算符。 假设变量A保持.true。 变量B保持.false。 那么 -

显示示例

操作者 描述
.and. 称为逻辑AND运算符。 如果两个操作数都不为零,则条件成立。 (A。和.B)是假的。
.or. 称为逻辑OR运算符。 如果两个操作数中的任何一个非零,则条件变为真。 (A。或.B)是真的。
.not. 称为逻辑非运算符。 用于反转其操作数的逻辑状态。 如果条件为真,则Logical NOT运算符将为false。 !(A。和。B)是真的。
.eqv. 称为逻辑等效运算符。 用于检查两个逻辑值的等效性。 (A .eqv.B)是假的。
.neqv. 称为逻辑非等价运算符。 用于检查两个逻辑值的非等价性。 (A .neqv.B)是真的。

Fortran中的运算符优先级

运算符优先级确定表达式中的术语分组。 这会影响表达式的计算方式。 某些运算符的优先级高于其他运算符; 例如,乘法运算符的优先级高于加法运算符。

例如,x = 7 + 3 * 2; 这里,x被赋值为13,而不是20,因为operator *的优先级高于+,所以它首先乘以3 * 2然后加到7中。

此处,具有最高优先级的运算符显示在表的顶部,具有最低优先级的运算符显示在底部。 在表达式中,将首先评估更高优先级的运算符。

显示示例

类别 操作者 关联性
逻辑NOT和负号 。不。 ( - ) 左到右
Exponentiation ** 左到右
Multiplicative */ 左到右
Additive + - 左到右
Relational << => = 左到右
Equality ==/= 左到右
Logical AND .and. 左到右
Logical OR .or. 左到右
Assignment = 右到左

Fortran - Decisions

决策结构要求程序员指定一个或多个要由程序评估或测试的条件,以及要执行的语句,如果条件被确定为真,并且可选地,如果是,则执行其他语句条件被确定为假。

以下是大多数编程语言中常见决策结构的一般形式 -

做决定

Fortran提供以下类型的决策构造。

Sr.No 声明和说明
1 If… then constructif… then… end if语句由一个逻辑表达式后跟一个或多个语句组成。
2 If… then...else constructif… then语句后面可以跟一个可选的else statement,else statement,在逻辑表达式为false时执行。
3 if ... else if ... else Statementif语句构造可以有一个或多个可选的else-if构造。 当if条件失败时,紧接着执行else-if 。 当else-if也失败时,执行其后继else-if语句(如果有的话),依此类推。
4 嵌套if构造您可以在另一个ifelse if语句中使用ifelse if语句。
5 选择案例构造select case语句允许根据值列表测试变量的相等性。
6 嵌套的选择案例构造您可以在另一个select case语句中使用一个select case语句。

Fortran - Loops

当您需要多次执行代码块时,可能会出现这种情况。 通常,语句按顺序执行:首先执行函数中的第一个语句,然后执行第二个语句,依此类推。

编程语言提供各种控制结构,允许更复杂的执行路径。

循环语句允许我们多次执行语句或语句组,以下是大多数编程语言中循环语句的一般形式 -

做决定

Fortran提供以下类型的循环结构来处理循环需求。 单击以下链接以检查其详细信息。

Sr.No 循环类型和描述
1 do 循环该构造使得语句或一系列语句能够迭代地执行,而给定条件为真。
2 do while 循环在给定条件为真时重复语句或语句组。 它在执行循环体之前测试条件。
3 嵌套循环您可以在任何其他循环结构中使用一个或多个循环结构。

循环控制语句 (Loop Control Statements)

循环控制语句将执行从其正常序列更改。 当执行离开作用域时,将销毁在该作用域中创建的所有自动对象。

Fortran支持以下控制语句。 单击以下链接以检查其详细信息。

Sr.No 控制声明和描述
1 exit如果执行exit语句,则退出循环,并且在结束do语句之后的第一个可执行语句处继续执行程序。
2 cycle如果执行循环语句,程序将在下一次迭代开始时继续。
3 stop如果希望停止执行程序,可以插入停止语句

Fortran - Numbers

Fortran中的数字由三种内在数据类型表示 -

  • 整数类型
  • 真实的类型
  • 复杂类型

整数类型

整数类型只能包含整数值。 以下示例提取可以在通常的四字节整数中保存的最大值 -

program testingInt
implicit none
   integer :: largeval
   print *, huge(largeval)
end program testingInt

编译并执行上述程序时,会产生以下结果 -

2147483647

请注意, huge()函数给出了特定整数数据类型可以保存的最大数字。 您还可以使用kind说明符指定字节数。 以下示例演示了这一点 -

program testingInt
implicit none
   !two byte integer
   integer(kind = 2) :: shortval
   !four byte integer
   integer(kind = 4) :: longval
   !eight byte integer
   integer(kind = 8) :: verylongval
   !sixteen byte integer
   integer(kind = 16) :: veryverylongval
   !default integer 
   integer :: defval
   print *, huge(shortval)
   print *, huge(longval)
   print *, huge(verylongval)
   print *, huge(veryverylongval)
   print *, huge(defval)
end program testingInt

编译并执行上述程序时,会产生以下结果 -

32767
2147483647
9223372036854775807
170141183460469231731687303715884105727
2147483647

真实的类型

它存储浮点数,例如2.0,3.1415,-100.876等。

传统上有两种不同的real类型:默认的真实类型和double precision类型。

但是,Fortran 90/95通过kind说明符提供了对实数和整数数据类型精度的更多控制,我们将在稍后研究。

以下示例显示了实际数据类型的使用 -

program division   
implicit none
   ! Define real variables   
   real :: p, q, realRes 
   ! Define integer variables  
   integer :: i, j, intRes  
   ! Assigning  values   
   p = 2.0 
   q = 3.0    
   i = 2 
   j = 3  
   ! floating point division
   realRes = p/q  
   intRes = i/j
   print *, realRes
   print *, intRes
end program division  

编译并执行上述程序时,会产生以下结果 -

0.666666687    
0

复杂类型

这用于存储复数。 复数有两部分:实部和虚部。 两个连续的数字存储单元存储这两个部分。

例如,复数(3.0,-5.0)等于3.0 - 5.0i

泛型函数cmplx()创建一个复数。 它产生的结果是,无论输入参数的类型如何,其实部和虚部都是单精度的。

program createComplex
implicit none
   integer :: i = 10
   real :: x = 5.17
   print *, cmplx(i, x)
end program createComplex

编译并执行上述程序时,会产生以下结果 -

(10.0000000, 5.17000008)

以下程序演示了复数运算 -

program ComplexArithmatic
implicit none
   complex, parameter :: i = (0, 1)   ! sqrt(-1)   
   complex :: x, y, z 
   x = (7, 8); 
   y = (5, -7)   
   write(*,*) i * x * y
   z = x + y
   print *, "z = x + y = ", z
   z = x - y
   print *, "z = x - y = ", z 
   z = x * y
   print *, "z = x * y = ", z 
   z = x/y
   print *, "z = x/y = ", z 
end program ComplexArithmatic

编译并执行上述程序时,会产生以下结果 -

(9.00000000, 91.0000000)
z = x + y = (12.0000000, 1.00000000)
z = x - y = (2.00000000, 15.0000000)
z = x * y = (91.0000000, -9.00000000)
z = x/y = (-0.283783793, 1.20270276)

数字的范围,精度和大小

整数范围,精度和浮点数的大小取决于分配给特定数据类型的位数。

下表显示整数的位数和范围 -

位数 最大价值 原因
64 9,223,372,036,854,774,807 (2**63)–1
32 2,147,483,647 (2**31)–1

下表显示了位数,最小值和最大值以及实数的精度。

位数 最大的价值 最小的价值 精确
64 0.8E+308 0.5E–308 15–18
32 1.7E+38 0.3E–38 6-9

以下示例说明了这一点 -

program rangePrecision
implicit none
   real:: x, y, z
   x = 1.5e+40
   y = 3.73e+40
   z = x * y 
   print *, z
end program rangePrecision

编译并执行上述程序时,会产生以下结果 -

x = 1.5e+40
          1
Error : Real constant overflows its kind at (1)
main.f95:5.12:
y = 3.73e+40
           1
Error : Real constant overflows its kind at (1)

现在让我们使用一个较小的数字 -

program rangePrecision
implicit none
   real:: x, y, z
   x = 1.5e+20
   y = 3.73e+20
   z = x * y 
   print *, z
   z = x/y
   print *, z
end program rangePrecision

编译并执行上述程序时,会产生以下结果 -

Infinity
0.402144760   

现在让我们看下溢 -

program rangePrecision
implicit none
   real:: x, y, z
   x = 1.5e-30
   y = 3.73e-60
   z = x * y 
   print *, z
   z = x/y
   print *, z
end program rangePrecision

编译并执行上述程序时,会产生以下结果 -

y = 3.73e-60
           1
Warning : Real constant underflows its kind at (1)
Executing the program....
$demo 
0.00000000E+00
Infinity

种类说明者

在科学编程中,通常需要知道正在进行工作的硬件平台的数据的范围和精度。

内部函数kind()允许您在运行程序之前查询硬件数据表示的详细信息。

program kindCheck
implicit none
   integer :: i 
   real :: r 
   complex :: cp 
   print *,' Integer ', kind(i) 
   print *,' Real ', kind(r) 
   print *,' Complex ', kind(cp) 
end program kindCheck

编译并执行上述程序时,会产生以下结果 -

Integer 4
Real 4
Complex 4

您还可以检查所有数据类型的类型 -

program checkKind
implicit none
   integer :: i 
   real :: r 
   character :: c 
   logical :: lg 
   complex :: cp 
   print *,' Integer ', kind(i) 
   print *,' Real ', kind(r) 
   print *,' Complex ', kind(cp)
   print *,' Character ', kind(c) 
   print *,' Logical ', kind(lg)
end program checkKind

编译并执行上述程序时,会产生以下结果 -

Integer 4
Real 4
Complex 4
Character 1
Logical 4

Fortran - Characters

Fortran语言可以将字符视为单个字符或连续字符串。

字符可以是从基本字符集中取出的任何符号,即字母,十进制数字,下划线和21个特殊字符。

字符常量是固定值字符串。

内在数据类型character存储字符和字符串。 字符串的长度可以由len说明符指定。 如果未指定长度,则为1.您可以按位置引用字符串中的单个字符; 最左边的字符位于第1位。

品格宣言

声明字符类型数据与其他变量相同 -

type-specifier :: variable_name

例如,

character :: reply, sex

你可以分配一个值,如,

reply = ‘N’ 
sex = ‘F’

以下示例演示了字符数据类型的声明和使用 -

program hello
implicit none
   character(len = 15) :: surname, firstname 
   character(len = 6) :: title 
   character(len = 25)::greetings
   title = 'Mr. ' 
   firstname = 'Rowan ' 
   surname = 'Atkinson'
   greetings = 'A big hello from Mr. Bean'
   print *, 'Here is ', title, firstname, surname
   print *, greetings
end program hello

编译并执行上述程序时,会产生以下结果 -

Here is Mr. Rowan Atkinson       
A big hello from Mr. Bean

字符串联

连接运算符//连接字符。

以下示例演示了这一点 -

program hello
implicit none
   character(len = 15) :: surname, firstname 
   character(len = 6) :: title 
   character(len = 40):: name
   character(len = 25)::greetings
   title = 'Mr. ' 
   firstname = 'Rowan ' 
   surname = 'Atkinson'
   name = title//firstname//surname
   greetings = 'A big hello from Mr. Bean'
   print *, 'Here is ', name
   print *, greetings
end program hello

编译并执行上述程序时,会产生以下结果 -

Here is Mr.Rowan Atkinson       
A big hello from Mr.Bean

Some 字符函数

下表显示了一些常用的字符函数以及描述 -

Sr.No 功能说明
1 len(string)它返回字符串的长度
2 index(string,sustring)它找到另一个字符串中子字符串的位置,如果找不到则返回0。
3 achar(int)它将整数转换为字符
4 iachar(c)它将字符转换为整数
5 trim(string)它返回删除了尾随空格的字符串。
6 scan(string, chars)对于“chars”中包含的任何字符的第一次出现,它从左到右搜索“string”(除非back = .true。)。 它返回一个给出该字符位置的整数,如果没有找到“chars”中的字符,则返回零。
7 verify(string, chars)它从左到右扫描“字符串”(除非back = .true。)第一次出现“chars”中没有包含的任何字符。 它返回一个给出该字符位置的整数,如果只找到“chars”中的字符,则返回零
8 adjustl(string)它左对齐“字符串”中包含的字符
9 adjustr(string)它正确地证明了“字符串”中包含的字符
10 len_trim(string)它返回一个等于“string”(len(string))长度的整数减去尾随空格的数量
11 repeat(string,ncopy)它返回一个长度等于“ncopy”的字符串乘以“string”的长度,并包含“ncopy”连接的“string”副本

例子1 (Example 1)

此示例显示了index函数的使用 -

program testingChars
implicit none
   character (80) :: text 
   integer :: i 
   text = 'The intrinsic data type character stores characters and   strings.'
   i=index(text,'character') 
   if (i /= 0) then
      print *, ' The word character found at position ',i 
      print *, ' in text: ', text 
   end if
end program testingChars

编译并执行上述程序时,会产生以下结果 -

The word character found at position 25
in text : The intrinsic data type character stores characters and strings.  

例子2 (Example 2)

此示例演示了trim功能的使用 -

program hello
implicit none
   character(len = 15) :: surname, firstname 
   character(len = 6) :: title 
   character(len = 25)::greetings
   title = 'Mr.' 
   firstname = 'Rowan' 
   surname = 'Atkinson'
   print *, 'Here is', title, firstname, surname
   print *, 'Here is', trim(title),' ',trim(firstname),' ', trim(surname)
end program hello

编译并执行上述程序时,会产生以下结果 -

 Here isMr.   Rowan          Atkinson       
 Here isMr. Rowan Atkinson

例子3 (Example 3)

这个例子演示了achar功能的使用 -

program testingChars
implicit none
   character:: ch
   integer:: i
   do i = 65, 90
      ch = achar(i)
      print*, i, ' ', ch
   end do
end program testingChars

编译并执行上述程序时,会产生以下结果 -

65  A
66  B
67  C
68  D
69  E
70  F
71  G
72  H
73  I
74  J
75  K
76  L
77  M
78  N
79  O
80  P
81  Q
82  R
83  S
84  T
85  U
86  V
87  W
88  X
89  Y
90  Z

检查字符的词法顺序

以下函数确定字符的词汇顺序 -

Sr.No 功能说明
1 lle(char, char)比较第一个字符是否在词法上小于或等于第二个字符
2 lge(char, char)比较第一个字符是否在词法上大于或等于第二个字符
3 lgt(char, char)比较第一个字符是否在词法上大于第二个字符
4 llt(char, char)比较第一个字符是否在词法上小于第二个字符

Example 4

以下功能演示了使用方法 -

program testingChars
implicit none
   character:: a, b, c
   a = 'A'
   b = 'a'
   c = 'B'
   if(lgt(a,b)) then
      print *, 'A is lexically greater than a'
   else
      print *, 'a is lexically greater than A'
   end if
   if(lgt(a,c)) then
      print *, 'A is lexically greater than B'
   else
      print *, 'B is lexically greater than A'
   end if  
   if(llt(a,b)) then
      print *, 'A is lexically less than a'
   end if
   if(llt(a,c)) then
      print *, 'A is lexically less than B'
   end if
end program testingChars

编译并执行上述程序时,会产生以下结果 -

a is lexically greater than A
B is lexically greater than A
A is lexically less than a
A is lexically less than B

Fortran - Strings

Fortran语言可以将字符视为单个字符或连续字符串。

字符串的长度可以只有一个字符,或者甚至可以是零长度。 在Fortran中,字符常量在一对双引号或单引号之间给出。

内在数据类型character存储字符和字符串。 字符串的长度可以由len specifier 。 如果未指定长度,则为1.您可以按位置引用字符串中的单个字符; 最左边的字符位于第1位。

字符串声明

声明字符串与其他变量相同 -

type-specifier :: variable_name

例如,

Character(len = 20) :: firstname, surname

你可以分配一个值,如,

character (len = 40) :: name  
name = “Zara Ali”

以下示例演示了字符数据类型的声明和使用 -

program hello
implicit none
   character(len = 15) :: surname, firstname 
   character(len = 6) :: title 
   character(len = 25)::greetings
   title = 'Mr.' 
   firstname = 'Rowan' 
   surname = 'Atkinson'
   greetings = 'A big hello from Mr. Beans'
   print *, 'Here is', title, firstname, surname
   print *, greetings
end program hello

编译并执行上述程序时,会产生以下结果 -

Here is Mr. Rowan Atkinson       
A big hello from Mr. Bean

字符串连接 (String Concatenation)

连接运算符//连接字符串。

以下示例演示了这一点 -

program hello
implicit none
   character(len = 15) :: surname, firstname 
   character(len = 6) :: title 
   character(len = 40):: name
   character(len = 25)::greetings
   title = 'Mr.' 
   firstname = 'Rowan' 
   surname = 'Atkinson'
   name = title//firstname//surname
   greetings = 'A big hello from Mr. Beans'
   print *, 'Here is', name
   print *, greetings
end program hello

编译并执行上述程序时,会产生以下结果 -

Here is Mr. Rowan Atkinson       
A big hello from Mr. Bean

提取子字符串

在Fortran中,您可以通过索引字符串从字符串中提取子字符串,在一对括号中给出子字符串的开始和结束索引。 这称为范围说明符。

以下示例显示如何从字符串'hello world'中提取子字符串'world' -

program subString
   character(len = 11)::hello
   hello = "Hello World"
   print*, hello(7:11)
end program subString 

编译并执行上述程序时,会产生以下结果 -

World

例子 (Example)

以下示例使用date_and_time函数来提供日期和时间字符串。 我们使用范围说明符分别提取年份,日期,月份,小时,分钟和第二个信息。

program  datetime
implicit none
   character(len = 8) :: dateinfo ! ccyymmdd
   character(len = 4) :: year, month*2, day*2
   character(len = 10) :: timeinfo ! hhmmss.sss
   character(len = 2)  :: hour, minute, second*6
   call  date_and_time(dateinfo, timeinfo)
   !  let’s break dateinfo into year, month and day.
   !  dateinfo has a form of ccyymmdd, where cc = century, yy = year
   !  mm = month and dd = day
   year  = dateinfo(1:4)
   month = dateinfo(5:6)
   day   = dateinfo(7:8)
   print*, 'Date String:', dateinfo
   print*, 'Year:', year
   print *,'Month:', month
   print *,'Day:', day
   !  let’s break timeinfo into hour, minute and second.
   !  timeinfo has a form of hhmmss.sss, where h = hour, m = minute
   !  and s = second
   hour   = timeinfo(1:2)
   minute = timeinfo(3:4)
   second = timeinfo(5:10)
   print*, 'Time String:', timeinfo
   print*, 'Hour:', hour
   print*, 'Minute:', minute
   print*, 'Second:', second   
end program  datetime

当您编译并执行上述程序时,它会提供详细的日期和时间信息 -

Date String: 20140803
Year: 2014
Month: 08
Day: 03
Time String: 075835.466
Hour: 07
Minute: 58
Second: 35.466

修剪字符串

trim函数接受一个字符串,并在删除所有尾随空白后返回输入字符串。

例子 (Example)

program trimString
implicit none
   character (len = *), parameter :: fname="Susanne", sname="Rizwan"
   character (len = 20) :: fullname 
   fullname = fname//" "//sname !concatenating the strings
   print*,fullname,", the beautiful dancer from the east!"
   print*,trim(fullname),", the beautiful dancer from the east!"
end program trimString

编译并执行上述程序时,会产生以下结果 -

Susanne Rizwan      , the beautiful dancer from the east!
 Susanne Rizwan, the beautiful dancer from the east!

字符串的左右调整

函数adjustl接受一个字符串并通过删除前导空格并将它们作为尾随空格附加来返回它。

函数adjustr接受一个字符串并通过删除尾随空白并将它们作为前导空格附加来返回它。

例子 (Example)

program hello
implicit none
   character(len = 15) :: surname, firstname 
   character(len = 6) :: title 
   character(len = 40):: name
   character(len = 25):: greetings
   title = 'Mr. ' 
   firstname = 'Rowan' 
   surname = 'Atkinson'
   greetings = 'A big hello from Mr. Beans'
   name = adjustl(title)//adjustl(firstname)//adjustl(surname)
   print *, 'Here is', name
   print *, greetings
   name = adjustr(title)//adjustr(firstname)//adjustr(surname)
   print *, 'Here is', name
   print *, greetings
   name = trim(title)//trim(firstname)//trim(surname)
   print *, 'Here is', name
   print *, greetings
end program hello

编译并执行上述程序时,会产生以下结果 -

Here is Mr. Rowan  Atkinson           
A big hello from Mr. Bean
Here is Mr. Rowan Atkinson    
A big hello from Mr. Bean
Here is Mr.RowanAtkinson                        
A big hello from Mr. Bean

在字符串中搜索子字符串

index函数接受两个字符串并检查第二个字符串是否是第一个字符串的子字符串。 如果第二个参数是第一个参数的子字符串,则它返回一个整数,该整数是第一个字符串中第二个字符串的起始索引,否则返回零。

例子 (Example)

program hello
implicit none
   character(len=30) :: myString
   character(len=10) :: testString
   myString = 'This is a test'
   testString = 'test'
   if(index(myString, testString) == 0)then
      print *, 'test is not found'
   else
      print *, 'test is found at index: ', index(myString, testString)
   end if
end program hello

编译并执行上述程序时,会产生以下结果 -

test is found at index: 11

Fortran - Arrays

数组可以存储相同类型的固定大小的顺序元素集合。 数组用于存储数据集合,但将数组视为相同类型的变量集合通常更有用。

所有阵列都包含连续的内存位置。 最低地址对应于第一个元素,最高地址对应于最后一个元素。

Numbers(1) Numbers(2) Numbers(3) Numbers(4)

数组可以是一维的(如矢量),二维的(如矩阵),Fortran允许您创建最多7维数组。

声明数组 (Declaring Arrays)

使用dimension属性声明数组。

例如,要声明一个名为number的一维数组,包含5个元素的实数,你写,

real, dimension(5) :: numbers

通过指定其下标来引用数组的各个元素。 数组的第一个元素的下标为1。 数组编号包含五个实数变量 - 数字(1),数字(2),数字(3),数字(4)和数字(5)。

要创建一个名为matrix的5 x 5二维整数数组,你可以写 -

integer, dimension (5,5) :: matrix  

您还可以声明一个具有一些显式下限的数组,例如 -

real, dimension(2:6) :: numbers
integer, dimension (-3:2,0:4) :: matrix  

分配值

您可以为单个成员分配值,例如,

numbers(1) = 2.0

或者,你可以使用循环,

do i  =1,5
   numbers(i) = i * 2.0
end do

一维数组元素可以使用称为数组构造函数的简写符号直接赋值,如,

numbers = (/1.5, 3.2,4.5,0.9,7.2 /)

please note that there are no spaces allowed between the brackets '( 'and the back slash '/'

例子 (Example)

以下示例演示了上面讨论的概念。

program arrayProg
   real :: numbers(5) !one dimensional integer array
   integer :: matrix(3,3), i , j !two dimensional real array
   !assigning some values to the array numbers
   do i=1,5
      numbers(i) = i * 2.0
   end do
   !display the values
   do i = 1, 5
      Print *, numbers(i)
   end do
   !assigning some values to the array matrix
   do i=1,3
      do j = 1, 3
         matrix(i, j) = i+j
      end do
   end do
   !display the values
   do i=1,3
      do j = 1, 3
         Print *, matrix(i,j)
      end do
   end do
   !short hand assignment
   numbers = (/1.5, 3.2,4.5,0.9,7.2 /)
   !display the values
   do i = 1, 5
      Print *, numbers(i)
   end do
end program arrayProg

编译并执行上述代码时,会产生以下结果 -

 2.00000000    
 4.00000000    
 6.00000000    
 8.00000000    
 10.0000000    
         2
         3
         4
         3
         4
         5
         4
         5
         6
 1.50000000    
 3.20000005    
 4.50000000    
0.899999976    
 7.19999981    

一些阵列相关术语

下表给出了一些与数组相关的术语 -

术语 含义
Rank 它是数组具有的维数。 例如,对于名为matrix的数组,rank为2,对于名为numbers的数组,rank为1。
Extent 它是维度上的元素数量。 例如,数组编号具有范围5,而名为matrix的数组在两个维度中都具有范围3。
Shape 数组的形状是一维整数数组,包含每个维度中的元素数(范围)。 例如,对于数组矩阵,形状为(3,3),数组数为(5)。
Size 它是数组包含的元素数。 对于数组矩阵,它是9,对于数组数字,它是5。

将数组传递给程序

您可以将数组作为参数传递给过程。 以下示例演示了该概念 -

program arrayToProcedure      
implicit none      
   integer, dimension (5) :: myArray  
   integer :: i
   call fillArray (myArray)      
   call printArray(myArray)
end program arrayToProcedure
subroutine fillArray (a)      
implicit none      
   integer, dimension (5), intent (out) :: a
   ! local variables     
   integer :: i     
   do i = 1, 5         
      a(i) = i      
   end do  
end subroutine fillArray 
subroutine printArray(a)
   integer, dimension (5) :: a  
   integer::i
   do i = 1, 5
      Print *, a(i)
   end do
end subroutine printArray

编译并执行上述代码时,会产生以下结果 -

1
2
3
4
5

在上面的示例中,子例程fillArray和printArray只能使用维度为5的数组调用。但是,要编写可用于任何大小的数组的子例程,可以使用以下技术重写它 -

program arrayToProcedure      
implicit  none    
   integer, dimension (10) :: myArray  
   integer :: i
   interface 
      subroutine fillArray (a)
         integer, dimension(:), intent (out) :: a 
         integer :: i         
      end subroutine fillArray      
      subroutine printArray (a)
         integer, dimension(:) :: a 
         integer :: i         
      end subroutine printArray   
   end interface 
   call fillArray (myArray)      
   call printArray(myArray)
end program arrayToProcedure
subroutine fillArray (a)      
implicit none      
   integer,dimension (:), intent (out) :: a      
   ! local variables     
   integer :: i, arraySize  
   arraySize = size(a)
   do i = 1, arraySize         
      a(i) = i      
   end do  
end subroutine fillArray 
subroutine printArray(a)
implicit none
   integer,dimension (:) :: a  
   integer::i, arraySize
   arraySize = size(a)
   do i = 1, arraySize
     Print *, a(i)
   end do
end subroutine printArray

请注意,程序使用size函数来获取数组的大小。

编译并执行上述代码时,会产生以下结果 -

1
2
3
4
5
6
7
8
9
10

数组部分

到目前为止,我们已经引用了整个数组,Fortran提供了一种使用单个语句引用多个元素或数组的一部分的简单方法。

要访问数组部分,您需要提供该部分的下限和上限,以及所有维度的步幅(增量)。 这种表示法称为subscript triplet:

array ([lower]:[upper][:stride], ...)

如果没有提到下限和上限,则默认为您声明的范围,并且步幅值默认为1。

以下示例演示了该概念 -

program arraySubsection
   real, dimension(10) :: a, b
   integer:: i, asize, bsize
   a(1:7) = 5.0 ! a(1) to a(7) assigned 5.0
   a(8:) = 0.0  ! rest are 0.0 
   b(2:10:2) = 3.9
   b(1:9:2) = 2.5
   !display
   asize = size(a)
   bsize = size(b)
   do i = 1, asize
      Print *, a(i)
   end do
   do i = 1, bsize
      Print *, b(i)
   end do
end program arraySubsection

编译并执行上述代码时,会产生以下结果 -

5.00000000    
5.00000000    
5.00000000    
5.00000000    
5.00000000    
5.00000000    
5.00000000    
0.00000000E+00
0.00000000E+00
0.00000000E+00
2.50000000    
3.90000010    
2.50000000    
3.90000010    
2.50000000    
3.90000010    
2.50000000    
3.90000010    
2.50000000    
3.90000010 

Array Intrinsic Functions

Fortran 90/95提供了几种内在程序。 它们可以分为7类。

Fortran - Dynamic Arrays

dynamic array是一个数组,其大小在编译时是未知的,但在执行时将是已知的。

使用属性allocatable声明动态数组。

例如,

real, dimension (:,:), allocatable :: darray    

但是,为了将内存分配给这样的数组,你必须提到数组的等级,即维度,你可以使用allocate函数。

allocate ( darray(s1,s2) )      

使用数组后,在程序中,应使用deallocate函数释放创建的内存

deallocate (darray)  

例子 (Example)

以下示例演示了上面讨论的概念。

program dynamic_array 
implicit none 
   !rank is 2, but size not known   
   real, dimension (:,:), allocatable :: darray    
   integer :: s1, s2     
   integer :: i, j     
   print*, "Enter the size of the array:"     
   read*, s1, s2      
   ! allocate memory      
   allocate ( darray(s1,s2) )      
   do i = 1, s1           
      do j = 1, s2                
         darray(i,j) = i*j               
         print*, "darray(",i,",",j,") = ", darray(i,j)           
      end do      
   end do      
   deallocate (darray)  
end program dynamic_array

编译并执行上述代码时,会产生以下结果 -

Enter the size of the array: 3,4
darray( 1 , 1 ) = 1.00000000    
darray( 1 , 2 ) = 2.00000000    
darray( 1 , 3 ) = 3.00000000    
darray( 1 , 4 ) = 4.00000000    
darray( 2 , 1 ) = 2.00000000    
darray( 2 , 2 ) = 4.00000000    
darray( 2 , 3 ) = 6.00000000    
darray( 2 , 4 ) = 8.00000000    
darray( 3 , 1 ) = 3.00000000    
darray( 3 , 2 ) = 6.00000000    
darray( 3 , 3 ) = 9.00000000    
darray( 3 , 4 ) = 12.0000000   

Use of Data 语句

data语句可用于初始化多个阵列,或用于阵列段初始化。

数据语句的语法是 -

data variable/list/...

例子 (Example)

以下示例演示了该概念 -

program dataStatement
implicit none
   integer :: a(5), b(3,3), c(10),i, j
   data a /7,8,9,10,11/ 
   data b(1,:) /1,1,1/ 
   data b(2,:)/2,2,2/ 
   data b(3,:)/3,3,3/ 
   data (c(i),i = 1,10,2) /4,5,6,7,8/ 
   data (c(i),i = 2,10,2)/5*2/
   Print *, 'The A array:'
   do j = 1, 5                
      print*, a(j)           
   end do 
   Print *, 'The B array:'
   do i = lbound(b,1), ubound(b,1)
      write(*,*) (b(i,j), j = lbound(b,2), ubound(b,2))
   end do
   Print *, 'The C array:' 
   do j = 1, 10                
      print*, c(j)           
   end do      
end program dataStatement

编译并执行上述代码时,会产生以下结果 -

 The A array:
           7
           8
           9
          10
          11
 The B array:
           1           1           1
           2           2           2
           3           3           3
 The C array:
           4
           2
           5
           2
           6
           2
           7
           2
           8
           2

Use of Where 语句

where语句允许您在表达式中使用数组的某些元素,具体取决于某些逻辑条件的结果。 如果给定条件为真,它允许在元素上执行表达式。

例子 (Example)

以下示例演示了该概念 -

program whereStatement
implicit none
   integer :: a(3,5), i , j
   do i = 1,3
      do j = 1, 5                
         a(i,j) = j-i          
      end do 
   end do
   Print *, 'The A array:'
   do i = lbound(a,1), ubound(a,1)
      write(*,*) (a(i,j), j = lbound(a,2), ubound(a,2))
   end do
   where( a<0 ) 
      a = 1 
   elsewhere
      a = 5
   end where
   Print *, 'The A array:'
   do i = lbound(a,1), ubound(a,1)
      write(*,*) (a(i,j), j = lbound(a,2), ubound(a,2))
   end do   
end program whereStatement

编译并执行上述代码时,会产生以下结果 -

 The A array:
           0           1           2           3           4
          -1           0           1           2           3
          -2          -1           0           1           2
 The A array:
           5           5           5           5           5
           1           5           5           5           5
           1           1           5           5           5

Fortran - Derived Data Types

Fortran允许您定义派生数据类型。 派生数据类型也称为结构,它可以由不同类型的数据对象组成。

派生数据类型用于表示记录。 例如,您想要在图书馆中跟踪您的图书,您可能希望跟踪每本图书的以下属性 -

  • Title
  • Author
  • Subject
  • Book ID

定义派生数据类型

要定义派生数据type ,请使用类型和end type语句。 。 type语句定义一个新的数据类型,为您的程序提供多个成员。 类型语句的格式是这样的 -

type type_name      
   declarations
end type 

以下是您声明Book结构的方式 -

type Books
   character(len = 50) :: title
   character(len = 50) :: author
   character(len = 150) :: subject
   integer :: book_id
end type Books

访问结构成员 (Accessing Structure Members)

派生数据类型的对象称为结构。

可以在类型声明语句中创建Books类型的结构,如 -

type(Books) :: book1 

可以使用组件选择器字符(%)访问结构的组件 -

book1%title = "C Programming"
book1%author = "Nuha Ali"
book1%subject = "C Programming Tutorial"
book1%book_id = 6495407

Note that there are no spaces before and after the % symbol.

例子 (Example)

以下程序说明了上述概念 -

program deriveDataType
   !type declaration
   type Books
      character(len = 50) :: title
      character(len = 50) :: author
      character(len = 150) :: subject
      integer :: book_id
   end type Books
   !declaring type variables
   type(Books) :: book1 
   type(Books) :: book2 
   !accessing the components of the structure
   book1%title = "C Programming"
   book1%author = "Nuha Ali"
   book1%subject = "C Programming Tutorial"
   book1%book_id = 6495407 
   book2%title = "Telecom Billing"
   book2%author = "Zara Ali"
   book2%subject = "Telecom Billing Tutorial"
   book2%book_id = 6495700
   !display book info
   Print *, book1%title 
   Print *, book1%author 
   Print *, book1%subject 
   Print *, book1%book_id  
   Print *, book2%title 
   Print *, book2%author 
   Print *, book2%subject 
   Print *, book2%book_id  
end program deriveDataType

编译并执行上述代码时,会产生以下结果 -

 C Programming                                     
 Nuha Ali                                          
 C Programming Tutorial            
   6495407
 Telecom Billing                                   
 Zara Ali                                          
 Telecom Billing Tutorial            
   6495700

结构数组

您还可以创建派生类型的数组 -

type(Books), dimension(2) :: list

阵列的各个元素可以访问为 -

list(1)%title = "C Programming"
list(1)%author = "Nuha Ali"
list(1)%subject = "C Programming Tutorial"
list(1)%book_id = 6495407

以下计划说明了这一概念 -

program deriveDataType
   !type declaration
   type Books
      character(len = 50) :: title
      character(len = 50) :: author
      character(len = 150) :: subject
      integer :: book_id
   end type Books
   !declaring array of books
   type(Books), dimension(2) :: list 
   !accessing the components of the structure
   list(1)%title = "C Programming"
   list(1)%author = "Nuha Ali"
   list(1)%subject = "C Programming Tutorial"
   list(1)%book_id = 6495407 
   list(2)%title = "Telecom Billing"
   list(2)%author = "Zara Ali"
   list(2)%subject = "Telecom Billing Tutorial"
   list(2)%book_id = 6495700
   !display book info
   Print *, list(1)%title 
   Print *, list(1)%author 
   Print *, list(1)%subject 
   Print *, list(1)%book_id  
   Print *, list(1)%title 
   Print *, list(2)%author 
   Print *, list(2)%subject 
   Print *, list(2)%book_id  
end program deriveDataType

编译并执行上述代码时,会产生以下结果 -

C Programming                                     
Nuha Ali                                          
C Programming Tutorial               
   6495407
C Programming                                     
Zara Ali                                          
Telecom Billing Tutorial                                      
   6495700

Fortran - Pointers

在大多数编程语言中,指针变量存储对象的内存地址。 但是,在Fortran中,指针是一种数据对象,它具有比仅存储内存地址更多的功能。 它包含有关特定对象的更多信息,如类型,等级,范围和内存地址。

指针通过分配或指针分配与目标相关联。

声明指针变量

使用pointer属性声明指针变量。

以下示例显示了指针变量的声明 -

integer, pointer :: p1 ! pointer to integer  
real, pointer, dimension (:) :: pra ! pointer to 1-dim real array  
real, pointer, dimension (:,:) :: pra2 ! pointer to 2-dim real array

指针可以指向 -

  • 动态分配内存的区域。
  • 与指针具有相同类型的数据对象,具有target属性。

为指针分配空间

allocate语句允许您为指针对象分配空间。 例如 -

program pointerExample
implicit none
   integer, pointer :: p1
   allocate(p1)
   p1 = 1
   Print *, p1
   p1 = p1 + 4
   Print *, p1
end program pointerExample

编译并执行上述代码时,会产生以下结果 -

1
5

当不再需要时,应该通过deallocate语句清空分配的存储空间,并避免累积未使用和不可用的内存空间。

目标和协会

目标是另一个正常变量,为它留出空间。 必须使用target属性声明目标变量。

使用关联运算符(=>)将指针变量与目标变量相关联。

让我们重写前面的例子,来证明这个概念 -

program pointerExample
implicit none
   integer, pointer :: p1
   integer, target :: t1 
   p1=>t1
   p1 = 1
   Print *, p1
   Print *, t1
   p1 = p1 + 4
   Print *, p1
   Print *, t1
   t1 = 8
   Print *, p1
   Print *, t1
end program pointerExample

编译并执行上述代码时,会产生以下结果 -

1
1
5
5
8
8

指针可以是 -

  • Undefined
  • Associated
  • Disassociated

在上面的程序中,我们使用=“运算符将指针p1与目标t1 associated 。 相关函数测试指针的关联状态。

nullify语句将指针与目标解除关联。

Nullify不会清空目标,因为可能有多个指针指向同一目标。 但是,清空指针也意味着无效。

例子1 (Example 1)

以下示例演示了这些概念 -

program pointerExample
implicit none
   integer, pointer :: p1
   integer, target :: t1 
   integer, target :: t2
   p1=>t1
   p1 = 1
   Print *, p1
   Print *, t1
   p1 = p1 + 4
   Print *, p1
   Print *, t1
   t1 = 8
   Print *, p1
   Print *, t1
   nullify(p1)
   Print *, t1
   p1=>t2
   Print *, associated(p1)
   Print*, associated(p1, t1)
   Print*, associated(p1, t2)
   !what is the value of p1 at present
   Print *, p1
   Print *, t2
   p1 = 10
   Print *, p1
   Print *, t2
end program pointerExample

编译并执行上述代码时,会产生以下结果 -

1
1
5
5
8
8
8
T
F
T
952754640
952754640
10
10

请注意,每次运行代码时,内存地址都会有所不同。

例子2 (Example 2)

program pointerExample
implicit none
   integer, pointer :: a, b
   integer, target :: t
   integer :: n
   t = 1
   a => t
   t = 2
   b => t
   n = a + b
   Print *, a, b, t, n 
end program pointerExample

编译并执行上述代码时,会产生以下结果 -

2  2  2  4

Fortran - Basic Input Output

到目前为止,我们已经看到我们可以使用read *语句从键盘读取数据,并分别使用print*语句将输出显示到屏幕。 这种形式的输入输出是free format I/O,它被称为list-directed输入输出。

免费格式的简单I/O具有以下形式 -

read(*,*) item1, item2, item3...
print *, item1, item2, item3
write(*,*) item1, item2, item3...

但是,格式化的I/O为您提供了更大的数据传输灵活性。

格式化输入输出

格式化输入输出的语法如下 -

read fmt, variable_list 
print fmt, variable_list 
write fmt, variable_list 

Where,

  • fmt是格式规范
  • 变量列表是要从键盘读取或写在屏幕上的变量列表

格式规范定义了格式化数据的显示方式。 它由一个字符串组成,其中包含括号中的edit descriptors列表。

edit descriptor指定确切的格式,例如,宽度,小数点后的数字等,其中显示字符和数字。

例如 (For example)

Print "(f6.3)", pi

下表描述了描述符 -

描述 描述
I 这用于整数输出。 这采用'rIw.m'形式,其中r,w和m的含义在下表中给出。 整数值在他们的领域是正确的。 如果现场宽度不足以容纳整数,那么该字段将填充星号。 print“(3i5)”,i,j,k
F 这用于实数输出。 这采用'rFw.d'形式,其中r,w和d的含义在下表中给出。 真正的价值观在他们的领域是正确的。 如果现场宽度不足以容纳实数,那么该字段将填充星号。 打印“(f12.3)”,pi
E 这用于指数表示法的实际输出。 'E'描述符语句采用'rEw.d'形式,其中r,w和d的含义在下表中给出。 真正的价值观在他们的领域是正确的。 如果现场宽度不足以容纳实数,那么该字段将填充星号。请注意,要打印出带有三位小数的实数,需要至少十位的字段宽度。 一个用于尾数的符号,两个用于零,四个用于尾数,两个用于指数本身。 通常,w≥d+ 7。 print“(e10.3)”,123456.0给出'0.123e + 06'
ES 这用于实际输出(科学记数法)。 这采用'rESw.d'形式,其中r,w和d的含义在下表中给出。 上面描述的'E'描述符与传统众所周知的'scienti fi c符号'略有不同。 科学符号的尾数在1.0到10.0的范围内,而E描述符的尾数在0.1到1.0的范围内。 真正的价值观在他们的领域是正确的。 如果现场宽度不足以容纳实数,那么该字段将填充星号。 这里,宽度场必须满足表达式w≥d+ 7 print“(es10.3)”,123456.0给出'1.235e + 05'
A 这用于字符输出。 这采用'rAw'形式,其中r和w的含义在下表中给出。 字符类型在他们的领域是正确的。 如果字段宽度不足以容纳字符串,那么字段将填充字符串的第一个“w”字符。 print“(a10)”,str
X 这用于空间输出。 采用'nX'形式,其中'n'是所需空格的数量。 print“(5x,a10)”,str
/ 斜杠描述符 - 用于插入空行。 采用“/”形式并强制下一个数据输出在新行上。 print“(/,5x,a10)”,str

以下符号与格式描述符一起使用 -

Sr.No 符号和描述
1 c列号
2 d实数输入或输出的小数位右边的位数
3 m要显示的最小位数
4 n要跳过的空格数
5 r重复计数 - 使用描述符或描述符组的次数
6 w字段宽度 - 用于输入或输出的字符数

例子1 (Example 1)

program printPi
   pi = 3.141592653589793238 
   Print "(f6.3)", pi 
   Print "(f10.7)", pi
   Print "(f20.15)", pi 
   Print "(e16.4)", pi/100 
end program printPi

编译并执行上述代码时,会产生以下结果 -

3.142
3.1415927
3.141592741012573
0.3142E-01

例子2 (Example 2)

program printName
implicit none
   character (len = 15) :: first_name
   print *,' Enter your first name.' 
   print *,' Up to 20 characters, please'
   read *,first_name 
   print "(1x,a)",first_name
end program printName

编译并执行上述代码时,会产生以下结果:(假设用户输入名称Zara)

Enter your first name.
Up to 20 characters, please
Zara 

例子3 (Example 3)

program formattedPrint
implicit none
   real :: c = 1.2786456e-9, d = 0.1234567e3 
   integer :: n = 300789, k = 45, i = 2
   character (len=15) :: str="IOWIKI"
   print "(i6)", k 
   print "(i6.3)", k 
   print "(3i10)", n, k, i 
   print "(i10,i3,i5)", n, k, i 
   print "(a15)",str 
   print "(f12.3)", d
   print "(e12.4)", c 
   print '(/,3x,"n = ",i6, 3x, "d = ",f7.4)', n, d
end program formattedPrint

编译并执行上述代码时,会产生以下结果 -

45
045
300789 45  2
300789 45  2
IOWIKI
123.457
0.1279E-08
n = 300789 d = *******

Format 语句

format语句允许您在一个语句中混合和匹配字符,整数和实际输出。 以下示例演示了这一点 -

program productDetails 
implicit none 
   character (len = 15) :: name
   integer :: id 
   real :: weight
   name = 'Ardupilot'
   id = 1
   weight = 0.08
   print *,' The product details are' 
   print 100
   100 format (7x,'Name:', 7x, 'Id:', 1x, 'Weight:')
   print 200, name, id, weight 
   200 format(1x, a, 2x, i3, 2x, f5.2) 
end program productDetails

编译并执行上述代码时,会产生以下结果 -

The product details are
Name:       Id:    Weight:
Ardupilot   1       0.08

Fortran - File Input Output

Fortran允许您从文件中读取数据并将数据写入文件。

在上一章中,您已经了解了如何从终端读取数据和向终端写入数据。 在本章中,您将学习Fortran提供的文件输入和输出功能。

您可以读取和写入一个或多个文件。 OPEN,WRITE,READ和CLOSE语句允许您实现此目的。

打开和关闭文件 (Opening and Closing Files)

在使用文件之前,您必须打开该文件。 open命令用于打开文件进行读写。 最简单的命令形式是 -

open (unit = number, file = "name").

但是,公开声明可能有一般形式 -

open (list-of-specifiers)

下表描述了最常用的说明符 -

Sr.No 说明和描述
1 [UNIT=] u单元号u可以是9-99范围内的任何数字,它表示文件,您可以选择任意数字,但程序中的每个打开文件都必须有唯一的编号
2 IOSTAT= ios它是I/O状态标识符,应该是整数变量。 如果open语句成功,则返回的ios值为零,否则为非零值。
3 ERR = err它是一个标签,控件在出现任何错误时跳转到该标签。
4 FILE = fname文件名,字符串。
5 STATUS = sta它显示文件的先前状态。 一个字符串,可以有三个值NEW,OLD或SCRATCH之一。 关闭或程序结束时创建并删除临时文件。
6 ACCESS = acc它是文件访问模式。 可以具有两个值中的任何一个,SEQUENTIAL或DIRECT。 默认为SEQUENTIAL。
7 FORM = frm它给出了文件的格式化状态。 可以具有两个值FORMATTED或UNFORMATTED中的任何一个。 默认值为UNFORMATTED
8 RECL = rl它指定直接访问文件中每条记录的长度。

打开文件后,将通过读写语句访问它。 完成后,应使用close语句关闭它。

close语句具有以下语法 -

close ([UNIT = ]u[,IOSTAT = ios,ERR = err,STATUS = sta])

请注意括号中的参数是可选的。

Example

此示例演示如何打开新文件以将某些数据写入文件。

program outputdata   
implicit none
   real, dimension(100) :: x, y  
   real, dimension(100) :: p, q
   integer :: i  
   ! data  
   do i=1,100  
      x(i) = i * 0.1 
      y(i) = sin(x(i)) * (1-cos(x(i)/3.0))  
   end do  
   ! output data into a file 
   open(1, file = 'data1.dat', status = 'new')  
   do i=1,100  
      write(1,*) x(i), y(i)   
   end do  
   close(1) 
end program outputdata

编译并执行上述代码时,它会创建文件data1.dat并将x和y数组值写入其中。 然后关闭文件。

读取和写入文件

read和write语句分别用于分别读取和写入文件。

它们具有以下语法 -

read ([UNIT = ]u, [FMT = ]fmt, IOSTAT = ios, ERR = err, END = s)
write([UNIT = ]u, [FMT = ]fmt, IOSTAT = ios, ERR = err, END = s)

大多数说明符已在上表中讨论过。

END = s说明符是一个语句标签,程序在到达文件结尾时跳转。

Example

此示例演示如何读取和写入文件。

在这个程序中,我们从文件中读取,我们在最后一个例子中创建了data1.dat,并在屏幕上显示它。

program outputdata   
implicit none   
   real, dimension(100) :: x, y  
   real, dimension(100) :: p, q
   integer :: i  
   ! data  
   do i = 1,100  
      x(i) = i * 0.1 
      y(i) = sin(x(i)) * (1-cos(x(i)/3.0))  
   end do  
   ! output data into a file 
   open(1, file = 'data1.dat', status='new')  
   do i = 1,100  
      write(1,*) x(i), y(i)   
   end do  
   close(1) 
   ! opening the file for reading
   open (2, file = 'data1.dat', status = 'old')
   do i = 1,100  
      read(2,*) p(i), q(i)
   end do 
   close(2)
   do i = 1,100  
      write(*,*) p(i), q(i)
   end do 
end program outputdata

编译并执行上述代码时,会产生以下结果 -

0.100000001  5.54589933E-05
0.200000003  4.41325130E-04
0.300000012  1.47636665E-03
0.400000006  3.45637114E-03
0.500000000  6.64328877E-03
0.600000024  1.12552457E-02
0.699999988  1.74576249E-02
0.800000012  2.53552198E-02
0.900000036  3.49861123E-02
1.00000000   4.63171229E-02
1.10000002   5.92407547E-02
1.20000005   7.35742599E-02
1.30000007   8.90605897E-02
1.39999998   0.105371222    
1.50000000   0.122110792    
1.60000002   0.138823599    
1.70000005   0.155002072    
1.80000007   0.170096487    
1.89999998   0.183526158    
2.00000000   0.194692180    
2.10000014   0.202990443    
2.20000005   0.207826138    
2.29999995   0.208628103    
2.40000010   0.204863414    
2.50000000   0.196052119    
2.60000014   0.181780845    
2.70000005   0.161716297    
2.79999995   0.135617107    
2.90000010   0.103344671    
3.00000000   6.48725405E-02
3.10000014   2.02930309E-02
3.20000005  -3.01767997E-02
3.29999995  -8.61928314E-02
3.40000010  -0.147283033    
3.50000000  -0.212848678    
3.60000014  -0.282169819    
3.70000005  -0.354410470    
3.79999995  -0.428629100    
3.90000010  -0.503789663    
4.00000000  -0.578774154    
4.09999990  -0.652400017    
4.20000029  -0.723436713    
4.30000019  -0.790623367    
4.40000010  -0.852691114    
4.50000000  -0.908382416    
4.59999990  -0.956472993    
4.70000029  -0.995793998    
4.80000019  -1.02525222    
4.90000010  -1.04385209    
5.00000000  -1.05071592    
5.09999990  -1.04510069    
5.20000029  -1.02641726    
5.30000019  -0.994243503    
5.40000010  -0.948338211    
5.50000000  -0.888650239    
5.59999990  -0.815326691    
5.70000029  -0.728716135    
5.80000019  -0.629372001    
5.90000010  -0.518047631    
6.00000000  -0.395693362    
6.09999990  -0.263447165    
6.20000029  -0.122622721    
6.30000019   2.53026206E-02
6.40000010   0.178709000    
6.50000000   0.335851669    
6.59999990   0.494883657    
6.70000029   0.653881252    
6.80000019   0.810866773    
6.90000010   0.963840425    
7.00000000   1.11080539    
7.09999990   1.24979746    
7.20000029   1.37891412    
7.30000019   1.49633956    
7.40000010   1.60037732    
7.50000000   1.68947268    
7.59999990   1.76223695    
7.70000029   1.81747139    
7.80000019   1.85418403    
7.90000010   1.87160957    
8.00000000   1.86922085    
8.10000038   1.84674001    
8.19999981   1.80414569    
8.30000019   1.74167395    
8.40000057   1.65982044    
8.50000000   1.55933595    
8.60000038   1.44121361    
8.69999981   1.30668485    
8.80000019   1.15719533    
8.90000057   0.994394958    
9.00000000   0.820112705    
9.10000038   0.636327863    
9.19999981   0.445154816    
9.30000019   0.248800844    
9.40000057   4.95488606E-02
9.50000000  -0.150278628    
9.60000038  -0.348357052    
9.69999981  -0.542378068    
9.80000019  -0.730095863    
9.90000057  -0.909344316    
10.0000000  -1.07807255    

Fortran - Procedures

procedure是一组执行定义明确的任务的语句,可以从您的程序中调用。 信息(或数据)作为参数传递给调用程序和过程。

有两种类型的程序 -

  • Functions
  • Subroutines

Function

函数是返回单个数量的过程。 函数不应修改其参数。

返回的数量称为function value ,它由函数名称表示。

Syntax

函数的语法如下 -

function name(arg1, arg2, ....)  
   [declarations, including those for the arguments]   
   [executable statements] 
end function [name]

以下示例演示了一个名为area_of_circle的函数。 它计算半径为r的圆的面积。

program calling_func
   real :: a
   a = area_of_circle(2.0) 
   Print *, "The area of a circle with radius 2.0 is"
   Print *, a
end program calling_func
! this function computes the area of a circle with radius r  
function area_of_circle (r)  
! function result     
implicit none      
   ! dummy arguments        
   real :: area_of_circle   
   ! local variables 
   real :: r     
   real :: pi
   pi = 4 * atan (1.0)     
   area_of_circle = pi * r**2  
end function area_of_circle

编译并执行上述程序时,会产生以下结果 -

The area of a circle with radius 2.0 is
   12.5663710   

请注意 -

  • 您必须在主程序和过程中指定implicit none
  • 被调用函数中的参数r称为dummy argument

结果选项

如果希望将返回值存储在函数名以外的其他名称中,则可以使用result选项。

您可以将返回变量名称指定为 -

function name(arg1, arg2, ....) result (return_var_name)  
   [declarations, including those for the arguments]   
   [executable statements] 
end function [name]
12345

子程序 (Subroutine)

子例程不返回值,但可以修改其参数。

Syntax

subroutine name(arg1, arg2, ....)    
   [declarations, including those for the arguments]    
   [executable statements]  
end subroutine [name]
12345

调用子程序

您需要使用call语句调用子例程。

以下示例演示了子例程交换的定义和用法,它更改了其参数的值。

program calling_func
implicit none
   real :: a, b
   a = 2.0
   b = 3.0
   Print *, "Before calling swap"
   Print *, "a = ", a
   Print *, "b = ", b
   call swap(a, b)
   Print *, "After calling swap"
   Print *, "a = ", a
   Print *, "b = ", b
end program calling_func
subroutine swap(x, y) 
implicit none
   real :: x, y, temp   
   temp = x  
   x = y 
   y = temp  
end subroutine swap
123456789101112131415161718192021

编译并执行上述程序时,会产生以下结果 -

Before calling swap
a = 2.00000000    
b = 3.00000000    
After calling swap
a = 3.00000000    
b = 2.00000000   
1234567

指定参数的意图

intent属性允许您指定在过程中使用参数的意图。 下表提供了intent属性的值 -

用作 说明
in intent(in) 用作输入值,在功能中未更改
out intent(out) 用作输出值,它们将被覆盖
inout intent(inout) 参数都被使用和覆盖

以下示例演示了该概念 -

program calling_func
implicit none
   real :: x, y, z, disc
   x = 1.0
   y = 5.0
   z = 2.0
   call intent_example(x, y, z, disc)
   Print *, "The value of the discriminant is"
   Print *, disc
end program calling_func
subroutine intent_example (a, b, c, d)     
implicit none     
   ! dummy arguments      
   real, intent (in) :: a     
   real, intent (in) :: b      
   real, intent (in) :: c    
   real, intent (out) :: d   
   d = b * b - 4.0 * a * c 
end subroutine intent_example
1234567891011121314151617181920

编译并执行上述程序时,会产生以下结果 -

The value of the discriminant is
   17.0000000    
123

递归程序

当编程语言允许您在同一函数内调用函数时,就会发生递归。 它被称为函数的递归调用。

当一个过程直接或间接地调用自身时,称为递归过程。 您应该在声明之前在recursive一词之前声明这种类型的过程。

递归使用函数时,必须使用result选项。

以下是一个示例,它使用递归过程计算给定数字的阶乘 -

program calling_func
implicit none
   integer :: i, f
   i = 15
   Print *, "The value of factorial 15 is"
   f = myfactorial(15)
   Print *, f
end program calling_func
! computes the factorial of n (n!)      
recursive function myfactorial (n) result (fac)  
! function result     
implicit none     
   ! dummy arguments     
   integer :: fac     
   integer, intent (in) :: n     
   select case (n)         
      case (0:1)         
         fac = 1         
      case default    
         fac = n * myfactorial (n-1)  
   end select 
end function myfactorial
1234567891011121314151617181920212223

内部程序

当程序包含在程序中时,它被称为程序的内部过程。 包含内部过程的语法如下 -

program program_name     
   implicit none         
   ! type declaration statements         
   ! executable statements    
   . . .     
   contains         
   ! internal procedures      
   . . .  
end program program_name
12345678910

以下示例演示了该概念 -

program mainprog  
implicit none 
   real :: a, b 
   a = 2.0
   b = 3.0
   Print *, "Before calling swap"
   Print *, "a = ", a
   Print *, "b = ", b
   call swap(a, b)
   Print *, "After calling swap"
   Print *, "a = ", a
   Print *, "b = ", b
contains   
   subroutine swap(x, y)     
      real :: x, y, temp      
      temp = x 
      x = y  
      y = temp   
   end subroutine swap 
end program mainprog   
123456789101112131415161718192021

编译并执行上述程序时,会产生以下结果 -

Before calling swap
a = 2.00000000    
b = 3.00000000    
After calling swap
a = 3.00000000    
b = 2.00000000   
1234567

Fortran - Modules

模块就像一个包,你可以保存你的函数和子程序,以防你编写一个非常大的程序,或者你的函数或子程序可以在多个程序中使用。

模块为您提供了一种在多个文件之间拆分程序的方法。

模块用于 -

  • 打包子程序,数据和接口块。
  • 定义可由多个例程使用的全局数据。
  • 声明可以在您选择的任何例程中使用的变量。
  • 将模块完全导入到另一个程序或子程序中以供使用。

模块的语法

一个模块由两部分组成 -

  • 声明声明的规范部分
  • a包含子程序和函数定义的部分

模块的一般形式是 -

module name     
   [statement declarations]  
   [contains [subroutine and function definitions] ] 
end module [name]
12345

将模块用于您的程序

您可以通过use语句将模块合并到程序或子例程中 -

use name  
12

请注意

  • 您可以根据需要添加任意数量的模块,每个模块将位于单独的文件中并单独编译。
  • 模块可用于各种不同的程序。
  • 模块可以在同一程序中多次使用。
  • 在模块规范部分中声明的变量对模块是全局的。
  • 模块中声明的变量在使用模块的任何程序或例程中成为全局变量。
  • use语句可以出现在主程序或使用特定模块中声明的例程或变量的任何其他子例程或模块中。

例子 (Example)

以下示例演示了该概念 -

module constants  
implicit none 
   real, parameter :: pi = 3.1415926536  
   real, parameter :: e = 2.7182818285 
contains      
   subroutine show_consts()          
      print*, "Pi = ", pi          
      print*,  "e = ", e     
   end subroutine show_consts 
end module constants 
program module_example     
use constants      
implicit none     
   real :: x, ePowerx, area, radius 
   x = 2.0
   radius = 7.0
   ePowerx = e ** x
   area = pi * radius**2     
   call show_consts() 
   print*, "e raised to the power of 2.0 = ", ePowerx
   print*, "Area of a circle with radius 7.0 = ", area  
end program module_example
1234567891011121314151617181920212223

编译并执行上述程序时,会产生以下结果 -

Pi = 3.14159274    
e =  2.71828175    
e raised to the power of 2.0 = 7.38905573    
Area of a circle with radius 7.0 = 153.938049   
12345

模块中变量和子程序的可访问性

默认情况下,模块中的所有变量和子例程都可以通过use语句使用模块代码的程序。

但是,您可以使用privatepublic属性控制模块代码的可访问性。 当您将某个变量或子例程声明为私有时,它在模块外部不可用。

例子 (Example)

以下示例说明了这一概念 -

在前面的示例中,我们有两个模块变量epi. 让我们将它们设为私有并观察输出 -

module constants  
implicit none 
   real, parameter,private :: pi = 3.1415926536  
   real, parameter, private :: e = 2.7182818285 
contains      
   subroutine show_consts()          
      print*, "Pi = ", pi          
      print*, "e = ", e     
   end subroutine show_consts 
end module constants 
program module_example     
use constants      
implicit none     
   real :: x, ePowerx, area, radius 
   x = 2.0
   radius = 7.0
   ePowerx = e ** x
   area = pi * radius**2     
   call show_consts() 
   print*, "e raised to the power of 2.0 = ", ePowerx
   print*, "Area of a circle with radius 7.0 = ", area  
end program module_example
1234567891011121314151617181920212223

当您编译并执行上述程序时,它会给出以下错误消息 -

   ePowerx = e ** x
   1
Error: Symbol 'e' at (1) has no IMPLICIT type
main.f95:19.13:
   area = pi * radius**2     
   1
Error: Symbol 'pi' at (1) has no IMPLICIT type
12345678

由于epi,都被声明为私有,因此程序module_example不再能够访问这些变量。

但是,其他模块子程序可以访问它们 -

module constants  
implicit none 
   real, parameter,private :: pi = 3.1415926536  
   real, parameter, private :: e = 2.7182818285 
contains      
   subroutine show_consts()          
      print*, "Pi = ", pi          
      print*, "e = ", e     
   end subroutine show_consts 
   function ePowerx(x)result(ePx) 
   implicit none
      real::x
      real::ePx
      ePx = e ** x
   end function ePowerx
   function areaCircle(r)result(a)  
   implicit none
      real::r
      real::a
      a = pi * r**2  
   end function areaCircle
end module constants 
program module_example     
use constants      
implicit none     
   call show_consts() 
   Print*, "e raised to the power of 2.0 = ", ePowerx(2.0)
   print*, "Area of a circle with radius 7.0 = ", areaCircle(7.0)  
end program module_example
123456789101112131415161718192021222324252627282930

编译并执行上述程序时,会产生以下结果 -

Pi = 3.14159274    
e = 2.71828175    
e raised to the power of 2.0 = 7.38905573    
Area of a circle with radius 7.0 = 153.938049   
12345

Fortran - Intrinsic Functions

内在函数是作为Fortran语言的一部分提供的一些常见且重要的函数。 我们已经在Arrays,Characters和String章节中讨论过这些函数中的一些。

内在函数可以归类为 -

  • 数字函数
  • 数学函数
  • 数字查询功能
  • 浮点操作函数
  • 位操作函数
  • 字符功能
  • 种类功能
  • 逻辑函数
  • 数组函数。

我们在Arrays章节中讨论了数组函数。 在下一节中,我们将简要介绍其他类别的所有这些功能。

在函数名称列中,

  • A表示任何类型的数字变量
  • R表示实数或整数变量
  • X和Y代表实际变量
  • Z表示复变量
  • W代表实数或复数变量

数值函数

Sr.No 功能说明
1 ABS (A)它返回A的绝对值
2 AIMAG (Z)它返回复数Z的虚部
3 AINT (A [, KIND])它将A的小数部分截断为零,返回一个实数,整数。
4 ANINT (A [, KIND])它返回一个实数值,最接近的整数或整数。
5 CEILING (A [, KIND])它返回大于或等于数字A的最小整数。
6 CMPLX (X [, Y, KIND])它将实变量X和Y转换为复数X + iY; 如果Y不存在,则使用0。
7 CONJG (Z)它返回任何复数Z的复共轭。
8 DBLE (A)它将A转换为双精度实数。
9 DIM (X, Y)它返回X和Y的正差。
10 DPROD (X, Y)它返回X和Y的双精度实数。
11 FLOOR (A [, KIND])它提供小于或等于数字A的最大整数。
12 INT (A [, KIND])它将数字(实数或整数)转换为整数,将实部截断为零。
13 MAX (A1, A2 [, A3,...])它返回参数的最大值,所有这些都是相同的类型。
14 MIN (A1, A2 [, A3,...])它返回参数的最小值,所有这些都是相同的类型。
15 MOD (A, P)它返回A除以A的余数,两个参数的类型相同(A-INT(A/P)* P)
16 MODULO (A, P)它返回A模P 😦 A-FLOOR(A/P)* P)
17 NINT (A [, KIND])它返回最接近的数字A的整数
18 REAL (A [, KIND])它转换为实际类型
19 SIGN (A, B)它返回A的绝对值乘以P的符号。基本上它将B的符号传递给A.

例子 (Example)

program numericFunctions
implicit none  
   ! define constants  
   ! define variables
   real :: a, b 
   complex :: z
   ! values for a, b 
   a = 15.2345
   b = -20.7689
   write(*,*) 'abs(a): ',abs(a),' abs(b): ',abs(b)   
   write(*,*) 'aint(a): ',aint(a),' aint(b): ',aint(b) 
   write(*,*) 'ceiling(a): ',ceiling(a),' ceiling(b): ',ceiling(b)   
   write(*,*) 'floor(a): ',floor(a),' floor(b): ',floor(b)  
   z = cmplx(a, b)
   write(*,*) 'z: ',z   
end program numericFunctions
1234567891011121314151617

编译并执行上述程序时,会产生以下结果 -

abs(a): 15.2344999   abs(b): 20.7688999    
aint(a): 15.0000000  aint(b): -20.0000000    
ceiling(a): 16  ceiling(b): -20
floor(a): 15  floor(b): -21
z: (15.2344999, -20.7688999)
123456

数学函数 (Mathematical Functions)

Sr.No 功能说明
1 ACOS (X)它以弧度为单位返回范围(0,π)中的反余弦值。
2 ASIN (X)它以弧度为单位返回范围(-π/ 2,π/ 2)的反正弦值。
3 ATAN (X)它以弧度为单位返回范围(-π/ 2,π/ 2)的反正切。
4 ATAN2 (Y, X)它以弧度为单位返回范围(-π,π)中的反正切。
5 COS (X)它以弧度返回参数的余弦值。
6 COSH (X)它以弧度为单位返回参数的双曲余弦值。
7 EXP (X)它返回X的指数值。
8 LOG (X)它返回X的自然对数值。
9 LOG10 (X)它返回X的常用对数(基数10)值。
10 SIN (X)它以弧度形式返回参数的正弦值。
11 SINH (X)它以弧度为单位返回参数的双曲正弦值。
12 SQRT (X)它返回X的平方根。
13 TAN (X)它以弧度为单位返回参数的正切值。
14 TANH (X)它以弧度形式返回参数的双曲正切值。

例子 (Example)

以下程序计算一段时间后射弹的水平和垂直位置x和y,

其中,x = ut cos a和y = ut sin a - g t2/2

program projectileMotion  
implicit none  
   ! define constants  
   real, parameter :: g = 9.8  
   real, parameter :: pi = 3.1415927  
   !define variables
   real :: a, t, u, x, y   
   !values for a, t, and u 
   a = 45.0
   t = 20.0
   u = 10.0
   ! convert angle to radians  
   a = a * pi/180.0  
   x = u * cos(a) * t   
   y = u * sin(a) * t - 0.5 * g * t * t  
   write(*,*) 'x: ',x,'  y: ',y   
end program projectileMotion
123456789101112131415161718

编译并执行上述程序时,会产生以下结果 -

x: 141.421356  y: -1818.57861  
12

Numeric Inquiry Functions

这些函数适用于某种整数和浮点运算模型。 函数返回与变量X相同类型的数字的属性,这可以是实数,在某些情况下是整数。

Sr.No 功能说明
1 DIGITS (X)它返回模型的有效位数。
2 EPSILON (X)它返回的数字几乎可以忽略不计。 换句话说,它返回最小值,使得REAL(1.0,KIND(X))+ EPSILON(X)不等于REAL(1.0,KIND(X))。
3 HUGE (X)它返回最大数量的模型
4 MAXEXPONENT (X)它返回模型的最大指数
5 MINEXPONENT (X)它返回模型的最小指数
6 PRECISION (X)它返回小数精度
7 RADIX (X)它返回模型的基础
8 RANGE (X)它返回十进制指数范围
9 TINY (X)它返回模型的最小正数

浮点操作函数 (Floating-Point Manipulation Functions)

Sr.No 功能说明
1 EXPONENT (X)它返回模型编号的指数部分
2 FRACTION (X)它返回数字的小数部分
3 NEAREST (X, S)它返回给定方向上最近的不同处理器编号
4 RRSPACING (X)它返回给定数字附近的模型数的相对间距的倒数
5 SCALE (X, I)它将real乘以其基数乘以整数幂
6 SET_EXPONENT (X, I)它返回数字的指数部分
7 SPACING (X)它返回给定数字附近的型号的绝对间距

位操作功能 (Bit Manipulation Functions)

Sr.No 功能说明
1 BIT_SIZE (I)它返回模型的位数
2 BTEST (I, POS)比特测试
3 IAND (I, J)逻辑和
4 IBCLR (I, POS)清楚一点
5 IBITS (I, POS, LEN)位提取
6 IBSET (I, POS)设置位
7 IEOR (I, J)独家OR
8 IOR (I, J)包容性或
9 ISHFT (I, SHIFT)逻辑转变
10 ISHFTC (I, SHIFT [, SIZE])循环移位
11 NOT (I)逻辑补充

字符函数

Sr.No 功能说明
1 ACHAR (I)它返回ASCII整理顺序中的第I个字符。
2 ADJUSTL (STRING)它通过删除任何前导空格和插入尾随空白来调整字符串
3 ADJUSTR (STRING)它通过删除尾随空白和插入前导空格来调整字符串。
4 CHAR (I [, KIND])它返回机器特定整理顺序中的第I个字符
5 IACHAR (C)它返回ASCII整理顺序中字符的位置。
6 ICHAR (C)它返回机器(处理器)特定整理顺序中字符的位置。
7 INDEX (STRING, SUBSTRING [, BACK])它返回STRING中最左边的(最右边,如果BACK是.TRUE。)SUBSTRING的起始位置。
8 LEN (STRING)它返回字符串的长度。
9 LEN_TRIM (STRING)它返回字符串的长度,不带尾随空白字符。
10 LGE (STRING_A, STRING_B)词汇量大于或等于
11 LGT (STRING_A, STRING_B)词汇大于
12 LLE (STRING_A, STRING_B)词汇小于或等于
13 LLT (STRING_A, STRING_B)词汇量小于
14 REPEAT (STRING, NCOPIES)重复串联
15 SCAN (STRING, SET [, BACK])它返回属于SET的STRING最左边的索引(最右边,如果BACK是.TRUE。),如果没有,则返回0。
16 TRIM (STRING)删除尾随空白字符
17 VERIFY (STRING, SET [, BACK])验证字符串中的字符集

Kind 函数

Sr.No 功能说明
1 KIND (X)它返回kind类型参数值。
2 SELECTED_INT_KIND (R)它返回指定指数范围的类型参数类型。
3 SELECTED_REAL_KIND ([P, R])实物类型参数值,给定精度和范围

逻辑功能

Sr.No 功能说明
1 LOGICAL (L [, KIND])在具有不同种类类型参数的逻辑类型的对象之间转换

Fortran - Numeric Precision

我们已经讨论过,在早期版本的Fortran中,有两种real类型:默认的真实类型和double precision类型。

但是,Fortran 90/95通过kind规范提供了对实数和整数数据类型精度的更多控制。

种类属性

不同种类的数字以不同方式存储在计算机内。 kind属性允许您指定内部存储数字的方式。 例如,

real, kind = 2 :: a, b, c
real, kind = 4 :: e, f, g
integer, kind = 2 :: i, j, k
integer, kind = 3 :: l, m, n
12345

在上面的声明中,实变量e,f和g比实变量a,b和c具有更高的精度。 整数变量l,m和n可以存储更大的值并且具有比整数变量i,j和k更多的存储位数。 虽然这取决于机器。

例子 (Example)

program kindSpecifier
implicit none
   real(kind = 4) :: a, b, c
   real(kind = 8) :: e, f, g
   integer(kind = 2) :: i, j, k
   integer(kind = 4) :: l, m, n
   integer :: kind_a, kind_i, kind_e, kind_l
   kind_a = kind(a)
   kind_i = kind(i)
   kind_e = kind(e)
   kind_l = kind(l)
   print *,'default kind for real is', kind_a
   print *,'default kind for int is', kind_i
   print *,'extended kind for real is', kind_e
   print *,'default kind for int is', kind_l
end program kindSpecifier
1234567891011121314151617

编译并执行上述程序时,会产生以下结果 -

default kind for real is 4
default kind for int is 2
extended kind for real is 8
default kind for int is 4
12345

查询变量的大小

有许多内在函数可以让您查询数字的大小。

例如, bit_size(i)内部函数指定用于存储的位数。 对于实数, precision(x)内部函数返回精度的小数位数,而range(x)内部函数返回指数的小数范围。

例子 (Example)

program getSize
implicit none
   real (kind = 4) :: a
   real (kind = 8) :: b
   integer (kind = 2) :: i
   integer (kind = 4) :: j
   print *,'precision of real(4) =', precision(a)
   print *,'precision of real(8) =', precision(b)
   print *,'range of real(4) =', range(a)
   print *,'range of real(8) =', range(b)
   print *,'maximum exponent of real(4) =' , maxexponent(a)
   print *,'maximum exponent of real(8) =' , maxexponent(b)
   print *,'minimum exponent of real(4) =' , minexponent(a)
   print *,'minimum exponent of real(8) =' , minexponent(b)
   print *,'bits in integer(2) =' , bit_size(i)
   print *,'bits in integer(4) =' , bit_size(j)
end program getSize
123456789101112131415161718

编译并执行上述程序时,会产生以下结果 -

precision of real(4) = 6
precision of real(8) = 15
range of real(4) = 37
range of real(8) = 307
maximum exponent of real(4) = 128
maximum exponent of real(8) = 1024
minimum exponent of real(4) = -125
minimum exponent of real(8) = -1021
bits in integer(2) = 16
bits in integer(4) = 32
1234567891011

获得亲切的价值

Fortran提供了两个内部函数来获得所需的整数和实数精度的类型值 -

  • selected_int_kind(r)
  • selected_real_kind([p,r])

selected_real_kind函数返回一个整数,该整数是给定小数精度p和十进制指数范围r所必需的种类型参数值。 小数精度是有效位数,小数指数范围指定最小和最大可表示数。 因此范围从10-r到10 + r。

例如,selected_real_kind(p = 10,r = 99)返回精度为10位小数所需的种类值,范围至少为10-99到10 + 99。

例子 (Example)

program getKind
implicit none
   integer:: i
   i = selected_real_kind (p = 10, r = 99) 
   print *,'selected_real_kind (p = 10, r = 99)', i
end program getKind
1234567

编译并执行上述程序时,会产生以下结果 -

selected_real_kind (p = 10, r = 99) 8
12

Fortran - Program Libraries

有各种Fortran工具和库。 有些是免费的,有些是付费服务。

以下是一些免费图书馆 -

  • RANDLIB,随机数和统计分布生成器
  • BLAS
  • EISPACK
  • GAMS-NIST可用数学软件指南
  • NIST的一些统计和其他例程
  • LAPACK
  • LINPACK
  • MINPACK
  • MUDPACK
  • NCAR数学图书馆
  • Netlib数学软件,论文和数据库的集合。
  • ODEPACK
  • ODERPACK,一组用于排名和排序的例程。
  • Expokit用于计算矩阵指数
  • SLATEC
  • SPECFUN
  • STARPAC
  • StatLib统计库
  • TOMS
  • 排序和合并字符串

以下图书馆不是免费的 -

  • NAG Fortran数值库
  • Visual Numerics IMSL库
  • Numerical Recipes

Fortran - Programming Style

编程风格就是在开发程序时遵循一些规则。 这些良好实践赋予您的程序可读性和明确性等价值。

一个好的程序应该具有以下特征 -

  • Readability
  • Proper logical structure
  • Self-explanatory notes and comments

例如,如果你发表如下评论,它将没有多大帮助 -

! loop from 1 to 10 
do i = 1,10  

但是,如果你正在计算二项式系数,并且需要这个循环用于nCr,那么这样的评论会有所帮助 -

! loop to calculate nCr 
do i = 1,10
  • 缩进代码块以使各种级别的代码清晰。
  • 自检代码确保不存在数字误差,如除零,负实数的平方根或负实数的对数。
  • 包括确保变量不采用非法或超出范围值的代码,即输入验证。
  • 不将检查放在不必要的位置并减慢执行速度。 例如 -
real :: x 
x = sin(y) + 1.0
if (x >= 0.0) then
   z = sqrt(x)
end if
  • 使用适当的算法清楚地编写代码。
  • 使用延续标记'&'拆分长表达式。
  • 制作有意义的变量名。

Fortran - Debugging Program

调试器工具用于搜索程序中的错误。

调试器程序逐步执行代码,并允许您在执行程序期间检查变量和其他数据对象中的值。

它加载源代码,你应该在调试器中运行程序。 调试器调试程序 -

  • 设置断点,
  • 单步执行源代码,
  • 设置观察点。

断点指定程序应停止的位置,特别是在关键代码行之后。 在断点处检查变量后执行程序。

调试器程序还逐行检查源代码。

监视点是需要检查某些变量值的点,尤其是在读取或写入操作之后。

gdb调试器

gdb调试器,GNU调试器附带Linux操作系统。 对于X windows系统,gdb附带一个图形界面,程序名为xxgdb。

下表提供了gdb中的一些命令 -

命令 目的
break 设置断点
run 开始执行
cont 继续执行
next 仅执行下一行源代码,而不进入任何函数调用
step 在函数调用的情况下,通过单步执行函数来执行下一行源代码。

dbx调试器

还有另一个用于Linux的调试器dbx调试器。

下表提供了dbx中的一些命令 -

命令 目的
stop[var] 变量var的值更改时设置断点。
停在[proc] 它在输入过程proc时停止执行
停在[线] 它在指定的行设置断点。
run 开始执行。
cont 继续执行。
next 仅执行下一行源代码,而不进入任何函数调用。
step 在函数调用的情况下,通过单步执行函数来执行下一行源代码。

Fortran - 有用的资源

以下资源包含有关Fortran的其他信息。 请使用它们来获得有关此主题的更多深入知识。

Fortran上的有用链接

posted @ 2023-03-04 08:52  沐多  阅读(257)  评论(0编辑  收藏  举报