Fortran 90 类参数
我无法理解 Fortran 90 的 kind
参数。 据我所知,它不能确定变量的精度(即浮点数或双精度),也不能确定变量的类型。
那么,它决定了什么以及它到底有什么用呢?
I am having trouble understanding Fortran 90's kind
parameter. As far as I can tell, it does not determine the precision (i.e., float or double) of a variable, nor does it determine the type of a variable.
So, what does it determine and what exactly is it for?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
变量的 KIND 是一个整数标签,它告诉编译器应该使用哪种受支持的类型。
请注意,尽管 KIND 参数与存储在该 KIND 变量中的字节数相同是很常见的,但 Fortran 标准并不要求这样做。
也就是说,在很多系统上,
但可能有编译器,例如:
对于整数和逻辑类型也是如此。
(如果我去挖掘,我可能会找到示例。在 usenet 组 comp.lang.fortran 中搜索
kind
来查找示例。那里有关于 Fortran 的最丰富的讨论,其中有一些经验丰富的人做出了贡献。 )因此,如果您不能指望特定类型的值在不同平台上为您提供相同的数据表示形式,您会怎么做? 这就是内部函数
SELECTED_REAL_KIND
和SELECTED_INT_KIND
的用途。 基本上,您告诉函数您需要能够表示哪种类型的数字,它将返回您需要使用的类型。我通常使用这些类型,因为它们通常给我 4 字节和 8 字节实数:
因此我可能随后将变量声明为:
请注意,这可能会在您使用混合语言程序时导致问题,并且您需要绝对指定字节数变量占据。 如果您需要确定,有一些查询内在函数可以告诉您每种类型的信息,您可以从中推断出变量的内存占用量、其精度、指数范围等。 或者,您可以恢复到非标准但常见的
real*4
、real*8
等声明样式。当您开始使用新的编译器时,值得查看编译器特定的类型值,以便您知道正在处理什么。 在网上搜索
kindfinder.f90
寻找一个方便的程序,它会告诉您编译器可用的类型。The KIND of a variable is an integer label which tells the compiler which of its supported kinds it should use.
Beware that although it is common for the KIND parameter to be the same as the number of bytes stored in a variable of that KIND, it is not required by the Fortran standard.
That is, on a lot of systems,
but there may be compilers for example with:
Similarly for integer and logical types.
(If I went digging, I could probably find examples. Search the usenet group comp.lang.fortran for
kind
to find examples. The most informed discussion of Fortran occurs there, with some highly experienced people contributing.)So, if you can't count on a particular kind value giving you the same data representation on different platforms, what do you do? That's what the intrinsic functions
SELECTED_REAL_KIND
andSELECTED_INT_KIND
are for. Basically, you tell the function what sort of numbers you need to be able to represent, and it will return the kind you need to use.I usually use these kinds, as they usually give me 4 byte and 8 byte reals:
So I might subsequently declare a variable as:
Note that this may cause problems where you use mixed language programs, and you need to absolutely specify the number of bytes that variables occupy. If you need to make sure, there are enquiry intrinsics that will tell you about each kind, from which you can deduce the memory footprint of a variable, its precision, exponent range and so on. Or, you can revert to the non-standard but commonplace
real*4
,real*8
etc declaration style.When you start with a new compiler, it's worth looking at the compiler specific kind values so you know what you're dealing with. Search the net for
kindfinder.f90
for a handy program that will tell you about the kinds available for a compiler.我建议使用Fortran 2008及更高版本;
INT8、INT16、INT32、INT64、REAL32、REAL64、REAL128
。 这是通过在 Fortran 2003 及更高版本中调用ISO_FORTRAN_ENV
来完成的。 Kind 参数提供了不一致的方式来确保您始终获得适当数量的位表示I suggest using the Fortran 2008 and later;
INT8, INT16, INT32, INT64, REAL32, REAL64, REAL128
. This is done by callingISO_FORTRAN_ENV
in Fortran 2003 and later. Kind parameters provides inconsistent way to ensure you always get the appropriate number of bit representation只是扩展其他(非常好的)答案,特别是 Andrej Panjkov 的答案:
确切地。 尽管如此,对于所有数字内在类型,KIND参数用于指定“处理器上数字的表示和行为的模型”(来自节的单词标准的 16.5),实际上意味着它们的位模型,这并不是 KIND 参数可以代表的唯一事物。
类型的 KIND 参数是程序员在编译时可以选择的其性质、模型或行为的任何变体。 例如,对于固有字符类型,kind 参数表示处理器上可用的字符集(ASCII、UCS-4...)。
您甚至可以在您定义的派生类型(后来来自 Fortran 2003)上定义您自己的模型/行为变体。 您可以创建一个变换矩阵类型,并拥有一个版本,其中 KIND=2 用于 2D 空间(其中基础数组为 3x3),KIND=3 用于 3D 空间(具有 4x4 基础数组)。 请记住,非内在类型没有自动类型转换。
Just expanding the other (very good) answers, specially Andrej Panjkov's answer:
Exactly. Even though, for all the numeric intrinsic types, the KIND parameter is used to specify the "model for the representation and behavior of numbers on a processor" (words from the Section 16.5 of the standard), that in practice means their bit model, that's not the only thing a KIND parameter may represent.
A KIND parameter for a type is any variation in its nature, model or behavior that is avaliable for the programmer to choose at compile time. For example, for the intrinsic character type, the kind parameter represents the character sets avaliable on the processor (ASCII, UCS-4,...).
You can even define your own model/behaviour variations on you defined Derived Types (from Fortran 2003 afterwards). You can create a Transform Matrix type and have a version with KIND=2 for 2D space (in which the underlying array would be 3x3) and KIND=3 for 3D space (with a 4x4 underlying array). Just remember that there is no automatic kind conversion for non-intrinsic types.
在《Portland Group Fortran 参考》中,
KIND
参数“指定内在数据类型的精度”。 因此,在声明中,变量
float64
声明为 8 字节实数(旧的 FortranDOUBLE PRECISION
),变量float32
声明为4 字节实数(旧的 FortranREAL
)。这很好,因为它允许您独立于所运行的编译器和机器来修复变量的精度。 如果您正在运行的计算需要比传统 IEEE 单精度实数更高的精度(如果您正在学习数值分析课程,则很有可能),但将变量声明为
real :: myVar< /code>,如果编译器将所有
和real
值默认设置为双精度,但更改编译器选项或将代码移动到具有不同默认大小的不同机器上 < code>realinteger
变量可能会导致一些令人讨厌的意外(例如,你的迭代矩阵求解器会崩溃)。Fortran 还包含一些函数,可帮助您选择所需的
KIND
参数 -SELECTED_INT_KIND
和SELECTED_REAL_KIND
- 但如果您刚刚学习,我此时不会担心这些。既然您提到您正在学习 Fortran 作为课程的一部分,您还应该在 Fortran 资源 也许可以查看您正在使用的编译器套件(例如 Portland Group 或 Intel)的参考手册 - 这些通常是免费提供的。
From the Portland Group Fortran Reference, the
KIND
parameter "specifies a precision for intrinsic data types." Thus, in the declarationthe variable
float64
declared as an 8-byte real (the old FortranDOUBLE PRECISION
) and the variablefloat32
is declared as a 4-byte real (the old FortranREAL
).This is nice because it allows you to fix the precision for your variables independent of the compiler and machine you are running on. If you are running a computation that requires more precision that the traditional IEEE-single-precision real (which, if you're taking a numerical analysis class, is very probable), but declare your variable as
real :: myVar
, you'll be fine if the compiler is set to default allreal
values to double-precision, but changing the compiler options or moving your code to a different machine with different default sizes forreal
andinteger
variables will lead to some possibly nasty surprises (e.g. your iterative matrix solver blows up).Fortran also includes some functions that will help pick a
KIND
parameter to be what you need -SELECTED_INT_KIND
andSELECTED_REAL_KIND
- but if you are just learning I wouldn't worry about those at this point.Since you mentioned that you're learning Fortran as part of a class, you should also see this question on Fortran resources and maybe look at the reference manuals from the compiler suite that you are using (e.g. Portland Group or Intel) - these are usually freely available.
kind 的用途之一可能是确保对于不同的机器或操作系统,它们确实使用相同的精度并且结果应该相同。 所以代码是可移植的。 例如,
现在这个变量a始终是r8类型,这是真正的“双精度”(因此它在计算机上占用64位内存),无论代码运行在什么机器/操作系统上。
另外,因此您可以编写类似的内容,
并且此 _r8 确保 1.0 转换为 r8 类型。
One of the uses of kind could be to make sure that for different machine or OS, they truly use the same precision and the result should be the same. So the code is portable. E.g.,
Now this variable a is always r8 type, which is a true "double precision" (so it occupies 64 bits of memory on the electronic computer), no matter what machine/OS the code is running on.
Also, therefore you can write things like,
and this _r8 make sure that 1.0 is converted to r8 type.
总结其他答案:kind 参数指定内部数据类型(例如整数和实数)的存储大小(从而间接指定精度)。
但是,现在推荐的方法不是在源代码中指定变量的种类值,而是使用编译器选项来指定我们想要的精度。 例如,我们在代码中写入:
real::abc
,然后使用编译选项-fdefault-real-8
(对于gfortran)来指定一个编译代码8 字节浮点数。 对于ifort,对应的选项是-r8
。更新:
看来这里的 Fortran 专家强烈反对上述推荐的方式。 尽管如此,我仍然认为上述方法是一种很好的做法,有助于减少在 Fortran 代码中引入错误的机会,因为它保证您在整个程序中使用相同的种类值(您确实需要使用不同的种类值的机会)代码的不同部分中的种类值很少见),从而避免了函数调用中虚拟参数和实际参数之间经常遇到的种类值不匹配的错误。
To summarize other answers: the kind parameter specifies storage size (and thus indirectly, the precision) for intrinsic data types, such as integer and real.
However, the recommended way now is NOT to specify the kind value of variables in source code, instead, use compiler options to specify the precision we want. For example, we write in the code:
real :: abc
and then compile the code by using the compiling option-fdefault-real-8
(for gfortran) to specify a 8 byte float number. For ifort, the corresponding option is-r8
.Update:
It seems Fortran experts here strongly object to the recommended way stated above. In spite of this, I still think the above way is a good practice that helps reduce the chance of introducing bugs in Fortran codes because it guarantees that you are using the same kind-value throughout your program (the chance that you do need use different kind-values in different parts of a code is rare) and thus avoids the frequently encountered bugs of kind-value mismatch between dummy and actual arguments in a function call.