Fortran 中的 KIND

KIND 并不直接对应变量所占用的字节数,在不同的编译器与系统中可能有不同的对应关系,例如最常见的系统有:

1
2
3
REAl(KIND=4)  :: xs   ! 4 byte ieee float
REAl(KIND=8) :: xd ! 8 byte ieee float
REAl(KIND=16) :: xq ! 16 byte ieee float

而有些编译器可能是:

1
2
3
REAL(KIND=1) :: XS   ! 4 BYTE FLOAT
REAL(KIND=2) :: XD ! 8 BYTE FLOAT
REAL(KIND=3) :: XQ ! 16 BYTE FLOAT

所以,为了提高代码的可移植性,一般不直接给 integer 或 real 变量类型赋予确定的字节长度,而是使用内置函数SELECTED_REAL_KIND and SELECTED_INT_KIND 从当前编译器中获取 KIND 的数值。例如,我想声明一个 15 位的 real 变量,首先调用内置函数:

1
2
!> Double precision real numbers, 15 digits, range 10⁻³⁰⁷ to 10³⁰⁷-1; 64 bits
integer, parameter :: dp = selected_real_kind(15, 307)

然后在程序中声明变量:

1
2
3
4
5
real(dp) :: a, b, c
real(kind=dp) :: a, b, c ! another equivalent statement
a = 1.0_dp
b = 3.5_dp
c = 1.34e8_dp

注意,这里的浮点数常数后面还加上了参量 KIND 的后缀,每次写个数都这么搞似乎太麻烦了些,不知道不写是不是也啊~~~?anyway,可以在 module 中统一定义参量 KIND ,然后在其它程序中引用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
!> Numerical storage size parameters for real and integer values
module kind_parameter
implicit none
public

!> Single precision real numbers, 6 digits, range 10⁻³⁷ to 10³⁷-1; 32 bits
integer, parameter :: sp = selected_real_kind(6, 37)
!> Double precision real numbers, 15 digits, range 10⁻³⁰⁷ to 10³⁰⁷-1; 64 bits
integer, parameter :: dp = selected_real_kind(15, 307)
!> Quadruple precision real numbers, 33 digits, range 10⁻⁴⁹³¹ to 10⁴⁹³¹-1; 128 bits
integer, parameter :: qp = selected_real_kind(33, 4931)

!> Char length for integers, range -2⁷ to 2⁷-1; 8 bits
integer, parameter :: i1 = selected_int_kind(2)
!> Short length for integers, range -2¹⁵ to 2¹⁵-1; 16 bits
integer, parameter :: i2 = selected_int_kind(4)
!> Length of default integers, range -2³¹ to 2³¹-1; 32 bits
integer, parameter :: i4 = selected_int_kind(9)
!> Long length for integers, range -2⁶³ to 2⁶³-1; 64 bits
integer, parameter :: i8 = selected_int_kind(18)

end module kind_parameter

如果不是跨系统使用自己的代码,直接在 Windows 环境下用 real(8) 就省事多了。

我似乎明白了为什么之前看到过别人的 Fortran 代码,连 0.0,1.0,…,9.0 都要用变量名定义。我使用的编程语言主要是 MATLAB(如果 MATLAB 可以被称为一门编程语言的话),对数据类型只关注整数,浮点数,字符这种大的类别的区分,对于这些数据占系统多少字节并不关心,但是 Fortran 中的变量还可以体现占用字节的信息。

主要参考文档

Doctor Fortran in “It Takes All KINDs”

Fortran 90 kind parameter

在看帖子时看到别人写的查询自己机器 KIND 变量并生成相应的 Fortran 源码的代码,kindfinder.f90