数学运算
1.4.1常量和变量类型
a) 常量
常量是指其值始终不变的一些量。整型、实型、双精度和复型常量是算数型常量,也为常数。
整型:默认值为4字节(其它为1,2,8字节,Compaq Visual Fortran允许在Alpha机上使用8字节整数)。4字节32位(bit)中用一位存放数值的符号,其余为数本身(用二进制表示)。第1位为O表示“正”,“1”表示“负”。由于用有限的内存单元存储一个整数,因此整数的范围是有限的:-231—231-1,即-2147483648—2147483647之间,大约为±21亿。
11111111 11111111 11111111 11111111 = -1
11111111 11111111 11111111 11111110 = -2
10000000 00000000 00000000 00000000 = -2147483648
01111111 11111111 11111111 11111111 = 2147483647
例:12345678 -256 (1,000,000 或 125. 是错误的)
1234567890123_8 (8字节整数) (F90)
912345678901_k (k为定义精度的参量) (F90)
实型:默认值为4字节(其它为8字节)。实数是有小数点的数,有效位数为7位,其绝对值的范围与计算机系统和精度型(单精度和双精度)有关。实数有两种表示形式:
小数形式:即日常习惯使用的小数形式。
3.141592 -0.125 3.0 -2. 等
3.14159265358979_8 (8字节实数) (F90)
2.7182818_p (p为定义精度的参量) (F90)
指数形式:用指数形式表示的实数由两部分组成,即数字部分和指数部分。
7.8E-12 -0.125E5
0.125D+45(双精度,8字节)
在计算机内存中存储一个实数(不论是用小数形式表示或以指数形式表示)时情况与整数不同。实数在内存中一律以指数形式存放,它由三个部分组成:(1)数符;(2)指数包括符号;(3)数字部分。数字部分最前面有一个隐含的小数点。用4个字节(32bit)来存储时,1位存储数的符号,7位存储指数部分,24位存储数字部分。由于存储指数部分和数字部分的值(bit)长是有限的,因此一个实数的有效数字和数的范围都是有限的。
如果以24位来存储一个数,它最大可以存储十进数为224-l(减1是因为规定小数点后第一个数字不能为零,以便充分利用有限的bit位来存储有效数字),即16777215。也就是说可以存放0—16777215这个范围内的数,超过这个范围的数是不能存储的。可见,只能有7位有效数字(16777215虽然是八位数,但并不是所有8值数都能有效存储)。如果某计算机系统用n个二进位来存储一个实数的数字部分,则该实数的十进制数的有效数字位数大体上略小于n/3。
一个实数的范围也是有限的,这主要是由于存储实数的指数部分的位长是有限的。如果一个数的绝对值超过此范围,就会出现“溢出”,绝对值比上界大的称为“上溢”,系统对此按数据出错处理。比下界小的称为“下溢”,大多数计算机系统将该数据按零处理。[e_141_01.f] [e_141_02.f90]
复 型:默认值为2×4字节(其它为8字节)。实部与虚部用括号围起来表示:(实数,实数)。
逻辑型:默认值为4字节(其它为1字节)。其值只能为:.TRUE.(真) 和 .FALSE.(假)。
字符型:1个字符为1字节(中文系统中为2字节)。用 ' '(F90:" ")围起来的字符串。
例:"I'm a boy." (長为10字节)
'I''m a boy.' (長为10字节)
数 组:这不是一种单独的类型,可把同类型的常量用一维维数括起来表示:(/常量,常量,...,常量/)。 (F90)
b) 变量
变量是指在程序运行期间其值是可以变化的量。系统为程序中的每一个变量开辟一个存储单元,用来存放变量的值。
常量是分为类型的,而变量是用来存放常量的,因此变量也相应地区分为整型变量INTEGER、实型变量REAL、双精度变量DOUBLE PRECISION、复型变量COMPLEX、逻辑型变量LOGICAL、字符型变量CHARACTER。在程序中应当说明哪些变量是整型变量,哪些变量是实型变量。变量在内存中所占的字节数和数据存储形式与相应类型的常数相同。例如,实型变量一般占4个字节,按指数形式存放。在程序中规定变量的类型可以用以下几种方法。
隐含约定:Fortran规定,凡以字母I,J,K,L,M,N六个字母开头的变量名,如无另外说明则为整型变量。以其它字母开头的变量为实型变量。可以将这个隐含约定称为“I—N规则” ,表示用I到N之间的字母开头的变量为整型。例如:I,J,IMAX,NUMBER,LINE,JOB,Kl为整型变量,而A,Bl,COUNT,AMOUNT,TOTAL,BOOK为实型变量。
类型指定:如果想改变“I—N规则”对变量类型的约束,可以用类型说明语句专门指定某些变量的类型。Fortran中有六个类型说明语句:
(1)INTEGER语句(整型说明语句)
(2)REAL语句(实型说明语句)
(3)DOUBLE PRECISION语句(双精度说明语句)
(4)COMPLEX语句(复型说明语句)
(5)LOGICAL语句(逻辑型说明语句)
(6)CHARACTER语句(字符型说明语句)
IMPLICIT语句(隐含说明语句)指定:可以用IMPLICIT语句将某一字母开头的全部变量指定为所需的类型,还可以用一个IMPLICIT语句同时指定几种类型。例如:
IMPLICIT INTEGER (A,C,T-V)
IMPLICIT REAL (I,J)
IMPLICIT INTEGER (A,B),REAL(I,K),INTEGER (X-Z)
注:(1) 以上三种方法中,以类型说明语句最优先,IMPLICIT语句次之,“I—N规则”的隐含约定级别最低。如下程序中IMAX变量为整型,而其它以I、J开头的变量为实型:
IMPLICIT REAL(I,J)
INTEGER IMAX
(2) 类型说明语句和IMPLICIT语句是非执行语句。
(3) 类型说明只在本程序单位内有效。
(4) IMPLICIT语句和类型说明语句应该出现在本程序单位中的所有执行语句之前,其中IMPLICIT语句又应在所有的类型说明语句之前。
1.4.2内在函数
用Fortran解题往往要用到一些专门运算。如求三角函数 , ,开根 ,绝对值 ,对数 ,指数 ,求一组数中最大数和最小数等。Fortran提供了一些系统内在函数来完成这些运算。程序设计者不必自己设计进行这些运算的语句组(即程序段或子程序),只需写出一个函数的名字以及结出一个或若干个自变量,就可以得到所需的值。例如:
SQRT(4.0) →
SIN(2.0) → 2(弧度)的正弦值 ← 注意三角函数中的自变量单位为弧度!
EXP(3.5) →
LOG(3.0) →
常用的Fortran77函数如下表所示。
函数名 | 含 义 | 应用例子 | 相当数学上的运算 |
ABS EXP SIN COS ASIN ACOS TAN ATAN LOG LOGlO INT MOD SIGN REAL MAX MIN | 求绝对值 指数运算 正弦值 余弦值 反正弦 反余弦 正切 反正切 自然对数 常用对数 取整 求余 求符号 转换为实型 求最大值 求最小值 | ABS(X) EXP(X) SIN(X) COS(X) ASIN(X) ACOS(X) TAN(X) ATAN(X) ALOG(X) ALOG10(X) INT(X) MOD(X1,X2) SIGN(Xl,X2) REAL(I) MAX0(I1,I2,I3) MIN(Xl,X2,X3) | ,取 的整数部分 (当 ), (当 ) |
内在函数的执行方法
Fortran将这些内在函数分别编成单个子程序,组成函数库,存在于外部介质(如磁盘)上。在完成源程序的编译之后,用LINK命令实现连接,即将已翻译成二进制指令的目标程序与函数库连接。也就是将程序中出现函数名的地方用函数库中相应的一组指令代入之,组成一个统一的“可执行目标块”。例如程序中出现一个SIN函数,在连接时就将一组求正弦值二进制指令直接插入到程序中出现SIN的地方。由于是插入到程序内部的,所以称为“内在函数”。
一个内在函数可要求一个或多个自变量
例如,SQRT函数只能有一个自变量,而MOD函数要求两个自变量,MAX和MIN函数要求两个以上自变量。注意当自变量个数规定为2个时,自变量的顺序不应任意颠倒,如MOD(8,3)表示8被3除的余数,其值为2,而MOD(3,8)则表示3被8除的余数,其值为3。当自变量个数为>2时,自变量的顺序无关。
函数的自变量是有类型的,函数值也是有类型的
例如MOD(8,3)中自变量8和3是整型,函数MOD(8,3)的值“2”也是整型,如果写成MOD(8.0,3.0),自变量是实型的,函数值也是实型的,其值为2.0。
函数名分为“通用名”和“专用名”
例如求余函数的“通用名”为MOD,“专用名”有三个(MOD,AMOD,DMOD)。根据自变量的类型就自动确定了函数值的类型,如MOD(8,3)的值为整型,而MOD(8.0,3.0)的值为实型。当调用子程序时如果用内在函数作为自变量(实参),必须使用该内在函数的专用名。
1.4.3算术表达式
a) 算术运算符和运算优先级
FORTRAN规定可以使用五种算术运算符号。它们是:
+ 表示“加”(或正号)
- 表示“减”(或负号)
* 表示“乘”
/ 表示“除”
** 表示“乘方”
请注意:乘号用“*”表示,不能写成“×”,以免与字母“X”混淆,也不能用“.”代替乘号。除号不能用“÷”号。两个运算符不能紧邻,如A*-B是不合法的,应写成A*(-B)。
不同的运算符按以下优先级次序:加,减 < 乘,除 < 乘方,括号( )中优先。同一优先级的两个运算,乘方按“先右后左”,其它按“先左后右”原则。
例: x + y*z → x + (y*z)
x*y**2 → x*(y**2)
x/y/z → (x/y)/z
x**y**z → x**(y**z)
3+5-6.0*8.0/4**2 → 3+5-48.0/16.0 = 5
例: 4b分之a → a/(4*b) 或 a/4/b,而a/4*b 和 a/4b是错误的。
如无自信时可用括号( ),对运算时间几乎无影响。
b) 算术表达式的含义和表示方法
所谓表达式是指一个或多个运算的组合。它是由Fortran的运算符和括号将各运算元素(包括常量、变量、函数、数组元素)连结起来的一个有值的式子。Fortran77允许使用四种表达式,即:算术表达式,关系表达式,逻辑表达式,字符表达式。
算术表达式中各运算元素都是算术量,使用的运算符只能是算术运算符,表达式的值也是一个算术量(即数值)。例如,下面就是一个Fortran算术表达式: (A-B)/C**2+SIN(X+Y) 。
请注意:
(1)由于用“/”号作为除号,因此在写除法运算式子时应加上必要的括号。
(2)乘号不能省略,如 ,必须写成A*SIN(X),而不能写成ASIN(X)。
(3)Fortran中无大、中、小括号之分,一律用小括号。
(4)乘方按“先右后左”原则处理。
(5)对单项运算符(如-A中的符号)相当于在它前面有一个运算量“0”,如:-A**2相当于0-A**2而非(-A)**2。
Fortran算术表达式的求值运算的优先次序为:① 括号 > ② 函数 > ③ ** > ④ * / > ⑤ + -,即括号内的运算级别最高,加减最低。例如,SQRT(3.*2)**2 → 。
c) 表达式运算中的类型
Fortran中的常量和变量是分类型的,允许在不同类型的算术量(包括整型、实型、双精度、复型)之间进行算术运算,但不允许在算术量和非算术量(如逻辑型、字符型)之间进行算术运算。F77作如下规定:
同类型的算术量之间运算的结果仍保持原类型。
特别要注意:两个整数相除的商也是整数。例如,5/2的值是2而不等于2.5,4**(-1)等于0, 应写为5**(1./3.)而非5**(1/3)。
如果参加运算的两个算术量为不同类型,则编译系统会自动将它们转换成同一类型后进行运算。
转换的规律是:将低级类型转换成高级类型。类型的级别如下:整型(低)→实型(高)。类型的转换是从左向右进行的,在遇到不同类型的算术量时才进行转换。例如:1/2*1.0等于0,而1./2*1对于0.5。
d) 运算的误差
整型量的运算是准确的,没有任何误差(只要在整数范围内)。而实型量的运算会出现一些误差。例如:11111.1×1111.11本应得12345654.321,但由于受实数有效位数的限制,只能得到12345654.0。又如:0.001+1246825.0-1246820.0本应得5.001。但由于有效位数的限制,也将产生误差。[e_143_01.f90] 为减小误差,在写表达式时应尽量使每一次运算结果都在有效位数范围之内,尽量不要使两个相差很大的数值直接相加或相减。在判断两个实数是否相等时,要特别慎重,最好改为判断 ,即A和B之差的绝对值如果小于 ( 为一个很小的数,如10-10),则认为A和B相等。
总之,在实数运算中应充分考虑到其可能出现的误差,而且在运算过程中误差会不断积累而增大,有时可能达到一个可观的程度。
1.4.4赋值语句
e) 算术赋值语句
赋值语句的作用是将一个确定的值赋给一个变量。其一般格式为:V=e,V代表一个变量名,e代表一个表达式。
Fortran77的赋值语句有三类:算术赋值语句、逻辑赋值语句、字符赋值语句。这里只讨论算术赋值语句。算术赋值语句的作用是将一个算术量赋予一个算术型变量。
赋值语句中的“=”号是“赋值”的符号,而不是等号。它的作用是将赋值号右边的表达式的值赋给其左边的变量。例如:赋值语句“A=3.0”的作用是将3.0送到变量A中。因此在阅读程序时对赋值号的理解应是带方向的。赋值语句“N=N十l”的作用是将N的原值加1再送回变量N中。
算术赋值语句兼有计算和赋值双重功能。即先计算出表达式的值;然后将该值赋给一个变量。在Fortran程序中的求值计算主要是用赋值语句来实现的。
赋值号左边只能是变量名(或数值元素名),而不能是表达式,赋值号右边可以是常量、变量或表达式。“X+Y=3.0”语句是不合法的,因为在内存中找不到一个“X+Y”的单元来存放3.0这个数值。
f) 执行时的类型转换
一个算术赋值语句中的被赋值的变量(V)和表达式(e)的类型可以相同,也可以不相同。F77作如下规定:
如果变量V与表达式e的类型相同,则直接进行赋值。
如果类型不同,则应先进行表达式的求值,然后将该表达式的值转换为被赋值变量的类型。如:
I=3.5*2.1
表达式3.5*2.1的值为7.35,实型。而变量I为整型,因此I的值等于7。又如:
T=3*5/7
表达式的值为2,整型。由于T为实型,故系统先将整数2转换成实数2.0,再赋给变量T,T的值为2.0。
当赋值号两侧的类型不同时,往往会产生程序设计者事先预想不到的结果。所以在编写程序时,应尽可能使贼值号两侧保持同类型。