我正在尝试学习 Fortran,我看到很多不同的定义被传递,我想知道他们是否正在尝试完成同样的事情。以下有什么区别?
integer*4
integer(4)
integer(kind=4)
我正在尝试学习 Fortran,我看到很多不同的定义被传递,我想知道他们是否正在尝试完成同样的事情。以下有什么区别?
integer*4
integer(4)
integer(kind=4)
在 Fortran >=90 中,最好的方法是使用内部函数来指定所需的精度——这既保证了可移植性,又保证了您获得所需的精度。例如,要获取至少支持 8 个十进制数字的整数,您可以使用i
:my_int
integer, parameter :: RegInt_K = selected_int_kind (8)
integer (kind=RegInt_K) :: i, my_int
RegInt_K
将(或您选择的任何名称)定义为 aparameter
后,您可以在整个代码中将其用作符号。这也使得改变精度变得容易。
请求 8 位或 9 位十进制数字通常会获得一个 4 字节整数。
integer*4
是一个常见的扩展,可以追溯到旧的 FORTRAN 以指定一个 4 字节整数。虽然,这种语法不是也从来不是标准的 Fortran。
integer (4)
or是orinteger (RegInt_K)
的缩写。 不同于且不可移植——语言标准没有指定种类的数值。大多数编译器使用4 字节整数 - 对于这些编译器并将提供相同的整数类型 - 但也有例外,因此不可移植并且最好避免使用。integer (kind=4)
integer (kind=RegInt_K)
integer (4)
integer*4
kind=4
integer*4
integer(4)
integer(4)
实数的方法类似。
更新:如果您不想通过所需的精度指定数字类型,而是通过它们将使用的存储来指定数字类型,Fortran 2008 提供了一种方法。use
实数和整数可以通过ing模块后的存储位数指定ISO_FORTRAN_ENV
,例如,对于 4 字节(32 位)整数:
use ISO_FORTRAN_ENV
integer (int32) :: MyInt
gfortran 手册在“内在模块”下有文档。
只是一个更明确的解释是什么。编译器有一个不同数字类型的表。所有整数类型都是基本类型的不同种类—— integer
。假设编译器有 1 字节、2 字节、4 字节、8 字节和 16 字节integer
(或real
)种类。在表中,编译器对每种类型都有一个索引——这个索引是种类编号。
许多编译器选择这个编号:
kind number number of bytes
1 1
2 2
4 4
8 8
16 16
但他们可以选择任何其他编号。明显的可能性之一是
kind number number of bytes
1 1
2 2
3 4
4 8
5 16
确实有编译器(至少 g77 和 NAG)选择了这种方法。还有一些选项可以改变这一点。因此kind
,数字不可移植integer(kind=4)
或integer(4)
意味着 4 字节整数或 8 字节整数,具体取决于编译器。
integer*4
在某种意义上是可移植的,它总是意味着 4 个字节。但另一方面,它不是可移植的,因为它从未成为任何标准的一部分。使用此表示法的程序在 Fortran 77、90 或任何其他 Fortran 中均无效。
要查看如何设置种类编号的正确选项,请参阅 MSB 的答案。
同样的概念也适用于real
数据类型。请参阅Fortran 90 kind 参数(mataap 的答案)。
我将参考@SteveLionel 最近撰写的这篇富有启发性的文章,并尝试涵盖迄今为止其他答案中没有的一些细节:
integer*n
或是一种常见的扩展,当时不同的计算机体系结构开始对整数和实数值的内存格式进行不同的设计,其中存储的值的大小以字节为单位。但是,这并没有说明这些值的范围或精度:例如,16 位整数的不同实现可以提供不同的范围和限制值。real*n
n
寄存器大小可以是 8、12、16、30、32、36、48、60 或 64 位,一些 CDC 机器有补码整数(整数允许负零!),PDP-11 行有几个不同的浮点数点格式取决于系列,IBM 360/370 对其浮点数进行了“十六进制规范化”等 [...] 这些扩展非常受欢迎,以至于许多程序员认为(甚至今天许多人认为)这种语法是标准 Fortran ; 不是!
当 Fortran 90 出现时,kind
参数被添加到语言中,以及内在的查询函数(特别kind
是selected_int_kind
和selected_real_kind
,还有其他的,如precision
、digits
、epsilon
...),以帮助程序员指定对精度和数字类型范围的最低要求(仍然没有官方提及存储模型或字节)。语法是integer(kind=n)
or even integer(n)
,其中n
是一个常量值,对应于编译器支持的一种整数。对于文字常量,语法是12_n
or 3.4e-2_n
。
这个解决方案的优点是 Fortran 没有(现在仍然没有)对数据类型的实现细节做出任何假设,而不是用于选择类型的查询函数的结果,因此代码由正在解决的问题,而不是语言或硬件。正如其他答案中所说,问题在于,每个编译器都可以选择他们的种类数,因此假设幻数 likeinteger(4)
不可移植。
默认类型依赖于实现,尽管从 Fortran 2008 开始,编译器只需要支持一种整数类型和两种实数类型。(在 Fortran 2018 中仍然如此,但还有一个附加要求,即至少一个整数种类支持 18 个十进制数字。)如果您编写一个没有种类说明符的常量文字,您将获得默认种类。
ieee_arithmetic
,您可以查询和选择具有 IEEE 浮点功能的实数类型(如果可用)。有些架构同时提供 IEEE 和非 IEEE 浮点类型,例如 HP(以前的 Compaq,以前的 DEC)Alpha。在这种情况下,您可以使用内部模块 IEEE_ARITHMETIC 中的 IEEE_SELECTED_REAL_KIND 来获得 IEEE 浮动类型。如果没有满足要求的受支持种类怎么办?在这种情况下,内在函数返回一个负数,这将(通常取决于上下文)触发编译时错误。
iso_fortran_env
内在模块,它具有查询编译器实现的类型的存储大小numeric_storage_size
的功能,具有像和之类的内在函数bit_size
。Fortran 2003 修订版的另一个新增功能是iso_c_binding
内在模块,它提供种类参数值以保证与 C 类型、存储、精度和范围的兼容性。内部模块 ISO_C_BINDING 为可与 C 类型互操作的 Fortran 类型声明常量,例如 C_FLOAT 和 C_INT。如果您要声明可与 C 互操作的变量和接口,请使用这些。
iso_fortran_env
以包括命名常量int8
、int16
、int32
m int64
、和real32
,其值对应于占据规定位数的整数和实数类型。问题是这些常量只保证存储大小,而不是精度或范围。仅当这正是您想要的时才使用它们。real64
real128
In my view, this is little better than the old *n extension in that it tells you that a type fits in that many bits, but nothing else about it. As an example, there's one compiler where REAL128 is stored in 128 bits but is really the 80-bit "extended precision" real used in the old x86 floating point stack registers. If you use these you might think you're using a portable feature, but really you're not and may get bitten when the kind you get doesn't have the capabilities you need.