相信很多学友都知道,加 D 的含义是,使得计算变为双精度计算。比如 dsin 为双精度的正弦函数,dacos 为双精度的反余弦函数。
而加 C ,可以使得计算变为复数计算。比如 cabs 为复数求绝对值(求模),而 csqrt 为复数开方。等等。
类似的还有:
C | 使计算变为复数计算 |
D | 使计算变为双精度计算(Kind=8) |
Q | 使计算变为四精度计算(Kind=16)(部分编译器) |
B | 使计算变为超短整型计算(Kind=1) |
II | 使计算变为短整型计算(Kind=2) |
I | 使计算变为整型计算(Kind=4) |
KI | 使计算变为长整型计算(Kind=8) |
另外,C 前缀,可以与 D, Q 前缀组合,比如 CDABS 为双精度复数求模,CQSQRT 为四精度复数开方。
第二. 关于 Generic Name 和 Specific Name
从F90以后,语法新增了 Generic Name 的用法。(详询彭国伦《Fortran95程序设计》323页,第11-3-1节,但叫法不同)
多个接口类似,功能相似的函数。可以捆绑在一起,形成一个通用的名字(Generic Name),此时他们原来的名字称为专有名(Specific Name)。在调用这些函数时,可以直接调用这个通用名(Generic Name),编译器实质上调用的,是根据参数的个数、类型、顺序自动选择匹配的专有名字(Specific Name)函数。
如上例,sin , dsin , qsin , csin , cdsin , cqsin 是专有名(Specific Name),他们共同捆绑成一个 sin 的通用名(Generic Name)。
当代码中书写 y = sin( x ) 的时候,是调用的通用名,而此时,编译器会根据 x 的类型,自动匹配,使得实际上调用的是 sin , dsin , qsin , csin , cdsin , cqsin 这些专有名中的其中一个。
当然,程序员也可以手动调用他们的专有名函数,比如 y = dsin( x ),此时,不管 x 是什么类型,都会被强制转换为专有名函数要求的类型。
两点需要注意:
1. sin 本身是通用名,同时 sin 可能也是 sin 通用名下捆绑的专有名。用于 real(kind=4) 的情况。对于 sin 来说,通用名sin和其中一个专有名sin是同名的。这样,程序员就不能单独调用专有名sin了。
但是其他一些 函数,比如 log通用名,它所有的专有名分别是 alog , dlog , qlog , clog , cdlog , cqlog ,而没有 log的专有名。
2. 不同的编译器,可能拥有不同的专有名。而通用名则是所有编译器都具有的。例如 IVF 的 sin 拥有 qsin 这个专有名,用于 real(kind=16) 的情况。但其他编译器不一定拥有。
第三. 加前缀(调用专有名)是否有必要?
答案是否定的。在绝大多数时候,我们不需要增加任何前缀。而可以直接调用通用名。
编译器会根据参数的类型,自动选择合适的函数来进行计算。比如 sin( 1.0D0 ),虽然没有前缀 d,但由于参数 1.0D0 是双精度的,所以编译器实际上也会使用 dsin 来计算,并获得双精度的精度。
因此,我们建议。在书写代码时,一律只书写函数名(不带任何前缀),比如 sin , cos , tan , sqrt , abs 等。让编译器根据参数类型自动适应函数(编译器自动选择专有名)。
只有在极少数的情况下,我们才有特意使用专有名的必要。比如:
1. 多个专有名对应同样的输入类型。比如:int( x ) ,当 x 的类型时 real(kind=8) 的时候,依然对应有多个专有名:
iidint , idint , kidint 分别返回 integer(kind=2 , 4 , 8 )
此时,编译器无法知道我们想要返回哪一种?此时,就有必要使用专有名。
2.想要的返回值和输入参数的类型不一样。我们就是想输入双精度,得到单精度。此时,我们也应该使用对应的专有名。
第四. 验证通用名自适应选择专业名函数
其实不需要验证,语法就是如此规定的。在此,我们使用一小段代码来验证。
Program www_fcode_cn Implicit None write( * , * ) acos(-1.0D0) , acos(-1.0) , dacos(-1.0D0) End Program www_fcode_cn
程序运行后结果为:
3.1415926535897931 3.14159274 3.1415926535897931
可见,第一个 PI 与第三个 PI 一模一样,acos 函数自动根据双精度参数适应为 dacos 函数。默认输出16位,也说明结果是双精度的结果。
而第二个 acos 参数为单精度,因此默认输出为 8 位。表示结果也是单精度。
第五. 为什么不提倡加前缀?
我们建议,在书写代码时,不使用任何前缀。
原因主要有两个:
1.前缀麻烦,需要书写时额外考虑应该用什么前缀。影响代码书写速度。
2.带前缀的函数,将来修改数据精度或类型时,修盖量巨大。
Program www_fcode_cn Implicit None Integer , parameter :: DP = 8 !// 将来只修改此处,如 DP = 16 Real( Kind = DP ) :: r = -1.0_DP write( * , * ) acos(r) , atan(r) , asin(r) !// 如果写为下面的方式,则还需修改三个函数名,比如 dacos 修改为 qacos !write( * , * ) dacos(r) , datan(r) , dasin(r) End Program www_fcode_cn