fortran95的使用方法5

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

第14章固有过程
固然,我们已经能够做到运用FORTRAN 95来描述任何的计算任务,因为FORTRAN 95所提供的数据类型,固有运算,派生类型,自定义运算,以及构造函数与子例行程序的方法,都足以使得我们应付任何的计算问题。

不过FORTRAN 95标准还提供了大量的科学计算的常规计算与函数,都可以作为固有过程直接使用,而不需要我们自己来编写源码。

这就好像对于一个汽车装配师,除了给他提供螺栓,轴承之类的标准零件,还给他提供更高层次的标准配件,例如各种型号的发动机,电机之类。

因此熟练掌握固有过程,将给我们带来如虎添翼的感觉。

FORTRAN 95把固有过程作为标准来提出,就意味着任何的FORTRAN 95的编译器实现版本,都必须能够提供它们:115个固有过程,其中包括109个固有函数和6个固有子例行程序。

当然不排除很多的编译器还提供额外的固有过程。

正是由于固有过程是属于FORTRAN 95的标准内容,因此和固有运算,例如+,一样,总是“随叫随到”,无论在哪个程序单位内部,只要使用某个固有过程的名称,就等于调用了该固有过程。

不过,如果它的名称被用户定义的函数或子例行程序所“侵占”,那么在下面的情况下,被调用的将是用户自定义的函数或子例行程序而不是固有过程:
●该自定义函数或子例行程序的界面是显式的;
●该自定义函数或子例行程序出现在EXTERNAL语句当中;
●该自定义函数属于语句函数。

当然上述的名称被侵权的有效范围只是该自定义函数或子例行程序的作用域。

相应的,固有过程也就只能在下面的情形下夺回被侵占的名称:
●不存在使用该名称的语句函数;
●它的名称出现在INTRINSIC语句当中;
●相应的用户定义的过程的界面是隐式的。

例如在一个模块或一个内部过程里面,由于它的界面是显式的,那么固有过程的名称就能够被侵占,除非固有过程的名称出现在一个有效的INTRINSIC语句当中。

下面我们主要讨论固有过程的按照功能的分类,以及每个种类的固有过程所能够完成的计算任务。

FORTRAN 95的固有过程主要分为如下5类:
●查询与数字操作函数;
●转换,置空以及传递函数;
●计算函数;
●数组函数;
●固有子例行程序。

在分别讨论上面5种固有过程之前,我们首先讨论13章所没有仔细讨论的固有过程的一些特点。

14.1 固有过程的分类与性质
固有过程可以从形式和功能两个方面来进行分类。

从形式的角度来看,固有过程分为如下两类:
●类过程;
●种过程。

所谓类过程是一个集合名称,类过程与种过程是一个集合与其元素的关系。

一个类过程由两个或多个种过程组成。

在固有过程中间之所以会出现这种关系,是因为过程所具体针对的变元的作为数据对象的类型与种别,是具有不同分类的,这样就导致同一个函数,当它的变元取不同类型或种别的数据值时,就需要对固有过程按照情形进行分类,甚至采用不同的过程名称,来应对相应的变元情况。

例如同样是求一个变量的绝对值,当该变量分别取实型和复型数值时,就对应了完全不同的计算过程,因此有必要给予不同的函数名称,尽管在数学的意义上,都是成为取绝对值。

在所有的115个固有过程当中,除了如下4个固有函数外,其他都是类过程:
●LGE;
●LGT;
●LLE;
●LLT。

对于每个类过程属下的种过程,显然都必定具有相应的类型,种别,甚至秩的属性。

许多的种过程具有专门的过程名称,在下面的表14-1当中列出了它们的全部名称以及相应的变元属性。

这些种过程的名称也可以直接用作过程引用,但并不提倡。

这些名称的主要用途是作为实元来传递,这时就必须使用种过程名称。

注意,在表中注明了少数种过程不能作为实元。

如果从功能的角度来对固有过程分类,那么除了上面的比较具体的5类之外,还可以从固有过程对数组的作用方式的角度,把固有过程分为两大类:逐元过程和变换过程。

●逐元过程
从数学的观点来看,这种过程的计算对象并不是数组,但是可以运用一种自然的方式使得这种过程能够作用于数组对象,并且得到相同形状的数组结果。

也就是使得该过程分别作用于数组的每个元素,把所有的过程结果再集合起来作为结果数组。

固有过程当中的大部分都属于逐元过程,包括:
●转换函数;
●计算函数(除了REPEAT,TRIM,DOT_PRODUCT,MATMUL之外);
●子例行程序MVBITS。

其他的所有固有过程就都不是逐元过程了。

●变换过程
固有过程里面逐元过程之外的所有过程都称为变换过程,因为从它们的定义的实质上看,就是作用于一个数组数据对象,得到一个标量或者数组结果,也就是一个变换的过程,而不是单独地作用于每个元素。

因此除了函数NULL之外,所有的变换过程或者是具有一个取数组值的哑元,或者是具有一个取数组值的实元,它们对数组的作用都是某种整体变换作用。

例如对于向量的乘积,就不能逐个元素地进行。

固有过程的引用正如一般过程的引用一样,可以使用关键词变元。

由于某些固有过程的变元是可选项,因此使用关键词能够省略相应的实元。

关键词变元也就是固有过程的哑元名称,在少数情况下,同一个名称会出现在不同的固有过程,不过这些名称基本上表示了相似的功能,因此不会带来什么实质问题。

这几个名称列举如下。

● DIM;
DIM主要用于数组简化函数以及其他一些数组函数,表示在函数的作用对象不是整个数组的情况下,数组的哪个维度被过程作用。

DIM取值为标量整型值,并且常常是可选变元。

●MASK;
MASK总是表示一种过滤器的作用,即把数组里面与过程作用无关的元素过滤掉,以免耗费资源。

MASK的是通过一个与被过滤数组相同形状的逻辑型数组来行使过滤功能的。

一般MASK为可选变元。

●KIND;
KIND一般用于转换函数,说明转换结果的种别参数。

KIND实元必须是一个标量整型初始化表达式,一般是可选的。

●BACK。

BACK作为一个可选的逻辑型变元用来表示逆序过程,即它所出现的固有过程的对于数据对象的反方向操作。

例如如果在固有过程INDEX当中出现了BACK=.TRUE.,那么INDEX的搜索操作就必须与正常方向相反,即从字符串的右端开始。

注意固有函数的非指针哑元都具有INTENT(IN)的属性,而指针哑元则不能改变其关联的实元或目标。

注1:该函数没有相应的类过程名称,它的结果为默认整型。

注2:该函数没有相应的类过程名称,它的结果为默认实型。

注3:标注星号*的函数不能用作实元。

注4:某些种过程名称与其类过程名称一样。

14.2 数据的表示模式
一些固有函数的计算结果是与数据的表示模式有关的,因此在这里我们首先给出数据的3种表示模式。

一个数据值的表示模式,决定了它的存储空间以及表示精度,包括如下3种模式:
●位模式;
●整数模式;
●实数模式。

有关数值的表示模式的信息对于很多的计算都是非常重要的,因为计算机的数据表示的离散性本质,使得我们不能期望很多的数学计算能够在计算机上面具有通常的行为,例如级数的收敛问题涉及到几乎所有的微积分数值计算,由于实数在计算机里面并不是可以无限位
地表示,所以必须知道某个具体的系统所能够达到的精度,才能够判断相应的计算能够做到什么程度。

所谓位模式就是把一个整型标量非负的数据对象B 表示为一个2进制的数字序列:
0121
...n b b b b -,
其中的每个数字取0或1。

把这样一个数字序列转换为10进制数值,采用如下的公式:
1
2
n k
k k B b -==
∑。

所谓整数模式的数值表示形式是一个任意进制的数字序列,但可以具有正负号,不能带有小数点,转换为19进制的公式为:
1
n k
k k I s b r
-==∑
其中:
● s 为+1或-1; ● r 为大于1的整数; ●
k
b 为整数并且0k
b r
≤<。

所谓实数模式采用如下的公式:
1
n
e
k
k
k R sr
b r
-==∑,
其中:
● s 为+1或-1; ● r 为大于1的整数;
● n 为尾数部分数字的数目,是一个大于1的整数; ●
k
b 为整数并且0k
b r
≤<;
● e 是某个最大值与最小值之间的整数,表示某种实现所能够表示的数值范围。

实数的一般实现方式是按照IEEE 2进制浮点标准,在单精度模式时,取:
r=2 n=24
125128e -≤≤
这样一个实数的尾数部分包括符号一起就占据了24位,而它的指数部分包括符号一起占据了8位,因此一个单精度实数表示要占据32位。

注意e 不能取-126,-127,-128这些数值,因为还需要额外地表示溢出,0,以及NaNs ,即非法值。

14.3 查询函数和数字操作函数
本节所讨论的函数并不是一般概念下对变元进行某种计算的函数,它的返回值是用来反映有关变元的状态与性质的各种信息。

所谓查询函数返回的是有关变元的数据类型的信息,因此返回值与变元的具体取值无关,而引用这种函数的实元也不需要预先定义。

所谓数字操作函数返回的是与实元取值相关的数值环境信息,因此引用这种函数的实元就需要给出定义。

根据所查询信息的不同种类,查询函数还可以分为7类,分别说明如下。

●字符查询函数。

这类函数只包含一个固有函数LEN。

它返回作为字符串的变元的字符长度值。

该长度值是在变元数据类型声明里面给出的,因此变元不需要给出具体的取值,就能够使用该查询函数。

对于哑长度的哑元,LEN返回的是其实元的长度值。

●位查询函数。

这类函数只包含一个固有函数BIT_SIZE。

如果一个整型标量数据对象采用了位模式的表示模式,那么使用该函数,就能够返回其变元的位模式表示公式里面的n的值。

其变元只需要是一个整数即可,不需要给出定义。

●种别查询函数。

这类函数包含3个固有函数KIND,SELECTED_INT_KIND,和SELECTED_REAL_KIND。

这3个固有函数都返回变元的种别参数,而变元的具体取值都不需要预先给出。

但它们的变元的取值范围是不同的。

●KIND的变元可以是任意的固有数据类型;
●SELECTED_INT_KIND的变元是整型变量,它返回的是表示10进制幂次范围的种
别参数;
●SELECTED_REAL_KIND的变元是实型变量,它返回的是表示10进制精度与10进
制幂次范围的种别参数。

●数组查询函数。

这类函数包含5个固有函数,它们返回的都是变元数组的各种属性参数。

它们的名称以及返回值列举在下表14-2。

这5个函数的变元的取值都不需要给出,但如果在SIZE,LBOUND,UBOUND这些函数里面使用可选变元DIM,则DIM的值需要预先定义。

●指针关联状态查询函数。

这类函数只包含一个固有函数ASSOCIATED,该函数的返回值为逻辑型值,根据该函数所带有的可选变元的不同情况,其返回值也分为以下3种情况:
●如果不出现可选变元,那么当变元具有指针属性,并且关联到一个目标时,返回值
为真。

●如果出现非指针的可选变元,那么当变元具有指针属性,并且关联到该可选变元时,
返回值为真。

●如果出现可选变元,并且该可选变元也是指针,那么当变元具有指针属性,并且与
可选变元都关联到同一个目标时,返回值为真。

●变元存在查询函数
这类函数只包含一个固有函数PRESENT。

它的变元必须是一个可选哑元的名称。

函数的返回值为逻辑型值。

当作为变元的哑元具有相应的实元时,函数返回值为真,否则为假。

●数值模式查询函数。

这类函数包含9个固有函数,它们返回的都是变元在整数模式和实数模式表示下的各种参数。

它们的名称以及返回值列举在下表14-3。

注意:
● 这些函数的变元都不需要预先定义。

● 它们都是类过程,因为它们都能够用于任意类型的实变元。

● 除了EPSILON,MINEXPONENT,MAXEXPONENT这3个函数之外,它们都能够用于任意类型的整型变元。

与数值模式查询函数类似,数字操作函数同样是基于数值的表示模式得到返回值的,但是它们最大的差别在于,数值模式查询函数所作用的变元代表了整个数值类型,返回的是有
关整个数值类型的表示模式参数,而数字操作函数所作用的变元只是在某种特定表示模式下的单个的具体的数值,因此它的变元需要在函数引用之前予以定义。

数字操作函数包括7种,它们的名称以及返回值列举在下表14-4。

这7个函数只能应用于实数环境,变元可以是任意类型的实数值,而且都是逐元函数。

14.4 转换函数,置空函数NULL以及传递函数
1. 转换函数
所谓转换函数就是能够把某种数据对象的类型与种别的某种组合转换为另外一种类型与种别的组合。

所有这些函数都是类函数,因为它们需要处理可能的各种类型与种别的组合,同时,它们也都是逐元的。

转换函数包括15个固有函数,它们的名称以及返回值列举在下表14-5。

2. 置空函数NULL
固有函数NULL返回一个能够赋值给指针变量的去关联的指针。

尽管它的功能与NULLIFY语句的功能一样,但是它们的应用场合不同:
●NULL函数应用于说明语句当中,以便对指针变量进行初始化,还可以在派生类型
定义当中定义其指针成员的默认初始化;
●NULLIFY语句作为可执行语句应用于程序当中。

固有函数NULL为变换函数而不是逐元函数。

3. 传递函数TRANSFER
固有函数TRANSFER能够在数据的不同类型与种别组合模式之间进行纯粹二进制数据传递,而不需要进行烦琐的类型与种别组合模式的转换。

当一个固有函数TRANSFER作用于一个源数据时,它的二进制表示形式,也就是它的物理存储模式被传递为函数结果,而函数结果的类型与种别组合模式则由函数的MOLD变元决定。

这样在传递过程当中就根本不需要进行类型与种别组合模式的转换。

TRANSFER为变换函数,而不是逐元函数,它的值常常是不具有可移植性的。

14.5 计算函数
所谓计算函数都是针对变元的计算,包括47个固有函数,分为如下三类:
●数值计算函数;
除了计算机所特有的数据类型以及精度限制之外,数值计算函数可以理解为就是相应的数学计算函数,数值计算函数表示了几乎所有最常用的基本数学函数。

●字符计算函数;
字符计算函数的主要功能就是对字符串进行编辑。

●位计算函数。

位计算函数基于数据的位模式表示进行操作与计算。

这3类固有函数的名称以及返回值分别列举在下面的表14-6,表14-7,和表14-8里面。

注意:
● 计算函数当中除了LGE,LGT,LLE,LLT之外都是类过程。

● 计算函数当中除了DOT_PRODUCT,MATMUL,REPEAT之外都是逐元过程。

●位计算函数的结果不可移植。

14.6 数组函数
数组函数包括17个固有函数,根据它们的功能可以分为5类如下:
●数组简化函数;
●数组构造函数;
●数组重组函数;
●数组操作函数;
●数组定位函数。

这5类函数的名称以及它们的返回值分别列举如下。

1. 数组简化函数
所谓数组简化函数,从形式上都是把一个数组经过计算之后得到一个标量,或者是得到一个秩为1的数组,它们的的名称以及返回值见表14-9。

2. 数组构造函数
所谓数组构造函数都是从变元数组的元素出发得到一个新的数组,它们的的名称以及返回值见表14-10。

3. 数组重组函数
数组重组函数只包含一个固有函数RESHAPE,它的功能是把一个秩为1的数组的元素重组为一个给定形状的数组。

4. 数组操作函数
数组操作函数对变元数组的元素进行重新排列,它们的的名称以及返回值见表14-11。

5. 数组定位函数
数组定位函数给出数组元素里面的最大值或最小值在数组当中,或在数组的某个维度当中的位置,它们的的名称以及返回值见表14-12。

14.7 固有子例行程序
固有子例行程序都只能通过CALL语句来引用,而不能作为实元传递,因为它们都没有特定名称。

固有子例行程序一共有6个,分别说明如下:
●CPU_TIME
该固有子例行程序返回以秒为单位的处理器时间,它不包含具有INTENT(OUT)属性的变元。

●DATE_AND_TIME
该固有子例行程序返回日期与时间信息作为一些具有INTENT(OUT)属性的变元的值。

●MVBITS
该固有子例行程序把一个二进制码序列从一个整型数据对象复制到另一个整型数据对象。

该固有子例行程序是唯一的逐元固有子例行程序。

●RANDOM_NUMBER
该固有子例行程序返回一个伪随机数值或伪随机数组作为变元的取值。

表面看来它应该可以作为一个函数,但是实际上它具有后效,即它每产生一个伪随机数结果,都会影响它底下的伪随机数生成器的变量的取值,因此它不是纯过程,而固有函数必须是纯过程。

●RANDOM_SEED
该固有子例行程序同样返回一个伪随机数值或伪随机数组作为变元的取值。

但它还允许对它底下的伪随机数生成器的变量进行特定的初始化或恢复原来的取值。

●SYSTEM_CLOCK
该固有子例行程序以整数形式返回处理器时钟信息,可以有几种格式,并且可以作为具有INTENT(OUT)属性的变元的值。

相关文档
最新文档