第4章 常量和变量 常量和变量都是程序中预留的用于保存数据的内存空间。常量的值在程序运行过程中始终不会发生变化。而变量的值在程序的运行过程中是可以变化的。在Fortran语言中,有五种基本的数据类型可供使用。他们分别是整型(INTEGER)、实型(REAL)、复型(COMPLEX)、字符型(CHARACTER)和逻辑型(LOGICAL)。按用途,又可以分数值型、字符型和逻辑型三种。相应的常量和变量也可以分为这三种。本章将按照用途介绍常量和变量的基本概念。
4.1 数值型常量及其类型 数值型常量的值在程序运行过程中不会发生改变,它们通常也被称为常数。数值型常量包括整型常量、实型常量和复型常量。本节主要介绍数值型常量的类型和基本概念。
4.1.1 整型常量 整型常量也称为整型常数或整数。按照所需存储空间的大小,又分为长整型和短整型两种。长整型占用4字节的存储空间,短整型则占用2字节的存储空间。默认情况下为长整型。有些编译器还提供额外的扩展整型常量,如Compaq Visual Fortran在x86及其兼容机上额外提供占用1字节空间的整型常量;在OpenVMS、Tru64UNIX和Linux系统中还提供占用8字节空间的整型常量。 由于存储整型常量的内存单元容量是一定的,因此整数所能表达的范围是有限的。长整型能够存储的数值范围为-231到231-1,即-2,147,483,648到2,147,483,647之间;短整型能够存储的数值范围为-215到215-1,即-32,768到32,767之间。整型常量可以包含正负号,也可以不包含(此时默认为正,即+2与2等价)。在Fortran77标准中,常量内部的空格不起任何作用,如“123”与“1□2□3”等价;但Fortran90/95标准中则不允许出现这种表达方式。
4.1.2 实型常量 实型常量也称为实型常数或实数。按照所需存储空间的大小,实数分为单精度和双精度两种。在实数的表达方式上,可以分为小数形式和指数形式两种。下面分别进行说明。 1.实数的精度:单精度实数占用4字节的存储空间,有效位数6到7位;双精度实数占用8字节的存储空间,有效位数15到16位。 2.实数的表达形式:当以小数形式来表达实数时,小数点的前面或后面可以不出现数字,但不允许小数点前后都不出现数字。例如,+10.4、-0.8、34.、.01等都是合法的。
4.1.3 复型常量 复型常量也称为复型常数或复数。按所需存储空间的大小分为单精度和双精度两种。复型常数是Fortran语言中特有的一种数据结构,能够同时存储复数的实部和虚部。在程序中,复型常数用一个括弧中的两个实数来表示。第一个实数表示复数的实部,第二个实数表示复数的虚部。比如:(3.0,6.3)和(1.0E2,2.0E3)。在存储的时候,复型常数会占据两个实数的存储单元。因此,单精度的复型常数占用8字节的存储空间;双精度的复型常数则需要占用16字节的存储空间。Compaq Visual Fortran在OpenVMS、Tru64UNIX和Linux系统中还提供占用32字节存储空间的复型常量。 复型常量中实部和虚部所表达的数的范围与同精度的实数是一致的。即单精度时的数值范围为1.17549435E-38到3.40282347E38;双精度时的数值范围为2.2250738585072013D-308到1.7976931348623158D308。
4.1.4 常量的存储形式 计算机在存储上述三种不同类型的常数时,并不区分数据的具体形式,而是统一将数据转化为二进制的形式进行存储。在转化的过程中,由于存储空间是一定的,因此存储实型常数时会产生存储误差的问题,即计算机的截断问题。在Compaq Visual Fortran安装目录的\DF98\BIN文件夹中有一个BITVIEWER程序可以查看各种数据在计算机中存储的二进制数据形式。通过它可以直观的了解计算机中数据的存储方式。软件的图形用户界面如图4.1所示,图中最下面一排的方框表示数据在计算机中的存储空间;每一个方框只有两个数值,即0和1;右侧有多个选项可供选择,用于表示数据所占用的存储空间。如4表示4字节、2表示2字节等。
4.1.5 符号常量 在程序中有时会经常用到同一个常数。如一些数学常数、物理常数等。如果每次都在程序中重复书写使用这些常数值,会显得很繁琐。Fortran允许用一个名字来对常量进行命名。比如常见的用PI来代表圆周率3.1415926535。此时称PI为“符号常量”或“符号常数”,即用符号来表示常量。在Fortran中,可以使用PARAMETER语句将一个符号声明为常量。比如将PI声明为常数3.1415926535,可以用如下的语句实现: PARAMETER (PI = 3.1415926535)
4.2 数值型变量及其类型 数值型变量主要是指整型、实型、复型三种变量。系统会为程序中的每一个变量按照其类型开辟一块存储单元,用于存储变量的值。每一个变量都需要用一个名字(变量名)来识别,并且同一个程序单元内不能用同一个变量名来命名不同的变量。本节主要介绍数值型变量的类型和基本概念。
4.2.1 数值型变量概述 数值型变量的分类同数值型常量一样。整型变量用来存储整型常量,实型变量用来存储实型常量,复型变量用来存储复型常量。在存储空间的分配上,同类型的变量与常量占据相同的存储空间。 变量名的作用是识别程序中的变量。Fortran中的变量名命名有一定的规则,主要有以下几条。 变量名中只能包含26个英文字母和0~9十个数字;在Fortran90/95标准中,还允许使用下划线“_”。 变量名的第一个字符必须是字母,不能是下划线“_”或数字。 在Fortran77标准中,变量名不允许超过6个字符;在Fortran90/95标准中,变量名不允许超过31个字符。
4.2.2 使用系统默认的隐含约定 Fortran中约定:在没有强制规定变量类型的情况下,如果变量名的首字母为I、J、K、L、M、N六个字母中的一个时,即认为该变量为整型变量,而以其他字母开头的变量则默认为实型变量。这就是所谓的“I-N规则”。“I-N规则”的使用有利有弊。好处就是不管在程序的什么位置,如果想要临时添加一个变量,只要按照“I-N规则”的约定取好变量名就可以使用了;缺点也是明显的,就是众多随意添加的变量使得程序阅读起来不是很方便,更有可能造成人为错误。比如下面的代码段就是一个典型的错误范例。 TEST0401.F90 ! 这是一个错误的变量定义范例 PROGRAM TEST0401 I = 3000 * 3 WRITE(*, *)l END PROGRAM TEST0401
4.2.3 使用类型说明语句声明 如果不想受“I-N规则”的约束,或是防止出现“I-N”规则下的常见错误,可以使用类型说明语句对变量的类型进行约定。 在Fortran中,基本的类型说明语句主要有六种。即INTEGER语句、REAL语句、DOUBL PRECISION语句、COMPLEX语句、LOGICAL语句和CHARACTER语句。数值型变量主要涉及到前四种语句。即INTEGER语句(整型说明语句)、REAL语句(实型说明语句)、DOUBL PRECISION语句(双精度说明语句)和COMPLEX语句(复型说明语句)。类型声明语句的语法形式如下: 类型说明语句[([KIND=]数字)] [::] 变量名[, 变量名……]
4.2.4 用隐含说明语句声明 除了上面提到的两种变量类型说明方法外,还可以用隐含说明语句(IMPLICIT语句)将以某一字母开头的所有变量都声明为同一种类型。该语句的语法形式如下: IMPLICIT 类型说明语句 (字母列表) 其中字母列表中的字母用逗号进行间隔。如果是连续的一串字母,可以用首尾字母间加符号“-”的方式来进行缩写。比如“C-H”。下面的声明代码将以字母A-G和N开头的变量都声明为整型: IMPLICIT INTEGER :: (A-G, N)
4.2.5 数值型变量声明及其应用 在编写程序的过程中,显式的声明所有用到的变量是一种良好的编程习惯,建议在编写实际的应用程序时使用“IMPLICIT NONE”来进行强制的变量类型检查。凡是没有进行类型说明的变量,在编译过程中都会被编译器找出来。 在三种类型规定方法中,以类型说明语句的优先级最高,IMPLICIT语句次之,“I-N规则”的级别最低;类型说明语句和IMPLICIT语句都是不可执行语句,必须出现在本程序单元中所有可执行语句之前;类型说明语句只能在本程序单元内有效;DOUBLE PRECISION语句在Fortran90/95标准完全可以用REAL(8)语句代替,目前已很少使用。
4.3 字符型常量及变量 文字处理能力是Fortran语言的另一特色。早期Fortran77中的文字处理能力较弱,在Fortran90/95标准中的文字处理能力已经大大加强。本节将介绍字符型常量和变量的基本概念。
4.3.1 字符型变量概述 字符型常量也称为字符串,它是用引号(单引号或双引号,Fortran77中只允许用单引号)括起来的若干个字符。字符串中的字符可以是计算机系统中允许使用的任意字符,通常会大于Fortran字符集。比如字符型常量‘BEIJING’,”PLANE”,”#$@%&”,”北京”都是合法的。 在计算机中,一个字符通常会占据一个字节的存储空间;但某些语言的字符在计算中需要多个字节的空间来存储。比如,一个汉字在计算机上会占据4字节的存储空间。字符型变量是用来存储字符型常量的变量,在程序中必须事先定义字符型变量才能使用。定义字符型常量可以使用CHARACTER语句,有四种定义字符型变量的语法形式,这些语法定义会在随后的小节进行介绍。
4.3.2 定义形式一 声明字符型变量的第一种语法形式如下。 CHARACTER [::] 变量名 4.3.2 定义形式一 声明字符型变量的第一种语法形式如下。 CHARACTER [::] 变量名 在这种形式的定义中,类型声明语句CHARACTER说明其后变量名所代表的变量为字符型变量。Fortran77和Fortran90/95中都可以采用这种形式进行声明。但需要注意,在Fortran77下不能出现分隔符“:”。采用这种形式进行声明时,允许对变量的长度进行说明,说明的方式有两种: 变量名*len 或 变量名(len)
4.3.3 定义形式二 第二种声明字符型变量的语法形式如下。 CHARACTER([KIND=]n) [::] 变量名 4.3.3 定义形式二 第二种声明字符型变量的语法形式如下。 CHARACTER([KIND=]n) [::] 变量名 在这种形式的声明中,关键字KIND用于指出赋值号“=”后所跟的数字n为变量的种别参数(有关种别参数的内容会在后面的小节进行讲解)。这个数字实际上就是说明声明语句中变量名所代表的变量的长度的,意义同定义形式一中的len。采用这种形式也可以定义字符型数组。在实际的编程实践中,也可以采用如下替代形式: CHARACTER([LEN=]n) [::] 变量名
4.3.4 定义形式三 第三种形式的字符型变量声明的语法形式如下。 CHARACTER*len [::] 变量名 4.3.4 定义形式三 第三种形式的字符型变量声明的语法形式如下。 CHARACTER*len [::] 变量名 在这种形式的声明中,类型声明语句后的星号“*”用于指明其后所跟的数字表示变量的长度,意义和前面两种定义形式中的差不多。这种形式的定义也可用于声明字符型数组,形式如下: CHARACTER*len [::] 变量名(dim) 其中的dim用于说明字符数组中的纬度的长,即长度。下面给出几个实例。 CHARACTER*20 :: String CHARACTER*10 :: Array_string(20)
4.3.5 定义形式四 在这种形式中,通过IMPLICIT语句来强迫使以某些字母开头的变量被默认处理成字符型。语法形式如下: 4.3.5 定义形式四 在这种形式中,通过IMPLICIT语句来强迫使以某些字母开头的变量被默认处理成字符型。语法形式如下: IMPLICIT CHARACTER[*数字] 字母表 IMPLICIT CHARACTER[(数字)] 字母表 Fortran77标准中通常采用前一种形式,Fortran90/95标准中通常采用后一种形式。定义中的数字表示字符型变量的长度,即能够存储多少个字符。当数字紧跟CHARACTER语句之后时,表示统一指定字符长度;当数字紧跟变量名之后时,表示单独指定字符的长度。如果统一指定的字符长度与变量个别指定的长度不一致时,以个别指定优先于统一指定。定义中括弧内的部分可有可无。比如: IMPLICIT CHARACTER(5) (G-N), CHARACTER X
4.3.6 字符型变量声明及其应用 实际上,只要字符变量的长度不为1,则可以将其看作数组来进行理解。正因为如此,在对字符型变量进行操作时,允许对字符型变量中的某一个或某几个存储位置上的数据进行单独操作。这在接下来的子字符串的相关内容中进行讲解。用PARAMETER语句配合CHARACTER语句还可以定义有名字符型常量,比如: CHARACTER(9) :: Name PARAMETER (Name = ‘Peter Pan’) 或 CHARACTER(9), PARAMETER :: Name = ‘Peter Pan’
4.3.7 子字符串的概念 在字符型数据的应用上,还有一个子字符串(Substring)的概念需要了解。所谓子字符串是指字符串的一部分。比如有一字符串为“Beijing”,则“Bei”、“jing”、“ei”等都是该字符串的子字符串。可以用下面的形式来引用子字符串: 字符串变量名([star]:[end]) 其中,star和end都是整型表达式。他们指定了要引用的子字符串在字符串中的起始和终止位置。
4.4 逻辑型常量及变量 逻辑量通常用于程序中的流程控制。在Fortran中,逻辑量主要有三种:逻辑常量、逻辑变量和关系表达式。本小节主要介绍Fortran中逻辑常量和逻辑变量的基本概念和应用。Fortran中的逻辑常量只有两个: TRUE,表示“真”,即满足逻辑条件; FALSE,表示“假”,即不满足逻辑条件。 例如,当A=0时,此时“A<1”的值就为TRUE(真),而“A<-1”的值就为FALSE(假)。逻辑常量又称为逻辑常数,在程序中,它们通常被赋给一个逻辑变量。 逻辑变量被用来存放逻辑常量,它的值只能是TRUE或FALSE中的一个。在程序中使用逻辑变量必须事先加以定义说明。在Fortran中,逻辑变量的定义是通过LOGICAL语句来实现的。该语句的一般形式为: LOGICAL[([KIND=]数字)] [::]变量名[,变量名]
4.5 变量的初始化 变量在定义之后,通常会由系统按照自身设置为变量赋给一个初值。这一过程称为变量的初始化。但是有些系统并不提供这种功能。如果贸然使用没有经过初始化的变量,很可能导致程序运行出错。 在Fortran中,允许在声明变量的同时设置变量的初置。在Fortran90/95中要设置变量的初置,可以将想要设置的初值直接写在声明的变量之后。使用这种方法进行初值的设置时,声明中的两个冒号不能省略。
4.6 赋值语句 变量在声明后就可以使用了,在使用过程中,变量需要保存不同的数据。将数据的值写进变量的过程就是赋值的过程。在Fortran语言中,除了一些专用的特殊语句外,最常用的赋值手段就是赋值语句。赋值语句就是等号“=”,在Fortran中有着广泛的用途。本节就将介绍赋值的概念和赋值语句的作用。
4.6.1 何为赋值 所谓赋值,就是将一个常量的值传输给一个相应的变量。在Fortran中,赋值除了通过DATA语句之外,还可以使用赋值语句来实现,并且赋值语句具有比DATA语句更广泛的用途。赋值语句的作用就是将一个确定的值赋给一个变量,语句的一般格式为: V=P 其中,表达式中的等号“=”就是赋值符;V代表一个变量名,P代表一个表达式。 Fortran的赋值语句有三种类型:算术赋值语句、逻辑赋值语句和字符赋值语句。算术赋值语句的作用是将一个算术量赋予一个算术型变量;逻辑赋值语句的作用是将一个逻辑量赋给一个逻辑性变量;字符赋值语句的作用就是将一个字符型数据赋给一个字符型变量。尽管用途不一样,但是三种赋值语句采用的都是同样的运算符号,即赋值符“=”。 赋值语句中的“=”号是赋值符,而不是等号。赋值符的作用是将赋值符右边表达式的值传递给赋值符左边的变量。例如,赋值语句“X=3.0”的作用是将数值3.0传递到变量X中。因此,在阅读程序代码时对赋值符的理解应是带方向的,即将什么数据赋值给什么变量。
4.6.2 赋值过程的类型转换 在一个算术赋值语句V=e中,赋值变量(V)和表达式(e)的类型既可以相同,也可以不相同。Fortran中对于赋值时的类型转换问题作了如下规定。 如果变量V与表达式e的类型相同,则直接进行赋值,不需进行类型转换。 如果变量V与表达式e的类型不同,则首先进行表达式的求值,然后求值的结果转换为赋值变量的类型。 在不同的类型之间进行转换是有限制条件的:数值型以及逻辑型数据之间允许相互赋值转换;数值型数据与字符型数据之间则不允许进行直接赋值转换,需要使用专用的字符函数;逻辑型数据不允许与字符型数据之间进行直接或间接的转换。 整型数据与实型数据的相互转换遵循如下规则:整形向实型转换时,保持数值的大小不变;实型向整型转换时,直接将实型的小数部分截去。 在由整型数据向逻辑型数据转换时,逻辑型数据的值由整型数据的奇偶来决定:当整型数据为奇数时,转换成的逻辑型数据的值为TRUE;当整型数据为偶数(包括0)时,转换成的逻辑型数据的值为FALSE。 在由实型数据向逻辑型数据转换时,实型数据会首先转换成整型,然后再由整型向逻辑型转换。