提问人:Sam 提问时间:7/3/2010 最后编辑:ZieziSam 更新时间:8/6/2023 访问量:36645
Fortran:整数*4 vs integer(4) vs integer(kind=4)
Fortran: integer*4 vs integer(4) vs 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
parameter
请求 8 或 9 位十进制数字通常会获得一个 4 字节整数。
integer*4
是一个常见的扩展,可以追溯到旧的 FORTRAN,用于指定一个 4 字节的整数。虽然,这种语法不是,也从来都不是标准的 Fortran。
integer (4)
or 是 或 的缩写。 与 Kind 不同,并且是不可移植的 -- 语言标准没有指定 Kind 的数值。大多数编译器使用 for 4 字节整数 -- 对于这些编译器,将提供相同的整数类型 -- 但也有例外,因此是不可移植的,最好避免。integer (RegInt_K)
integer (kind=4)
integer (kind=RegInt_K)
integer (4)
integer*4
kind=4
integer*4
integer(4)
integer(4)
实数的方法与此类似。
更新:如果您不想按所需的精度指定数值类型,而是按它们将使用的存储来指定数值类型,Fortran 2008 提供了一个方法。实数和整数可以通过模块后的存储位数来指定,例如,对于 4 字节(32 位)整数:use
ISO_FORTRAN_ENV
use ISO_FORTRAN_ENV
integer (int32) :: MyInt
gfortran 手册在“内部模块”下有文档。
评论
只是一个更明确的解释,什么是那种。编译器具有不同数值类型的表。所有整数类型都是基本类型-- .的不同种类假设编译器有 1 个字节、2 个字节、4 个字节、8 个字节和 16 个字节(或)种类。在表中,编译器对每一种类型都有一个索引——这个索引是种类编号。integer
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)选择这种方法。还有一些选项可以更改此设置。因此,数字不可移植,或者表示 4 字节整数或 8 字节整数,具体取决于编译器。kind
integer(kind=4)
integer(4)
integer*4
从某种意义上说是可移植的,它总是意味着 4 个字节。但另一方面,它不是可移植的,因为它从未成为任何标准的一部分。使用此表示法的程序在 Fortran 77、90 或任何其他 Fortran 中无效。
要查看正确的选项,如何设置种类编号,请参阅 M.S.B. 的答案。
同样的概念也适用于数据类型。请参阅 Fortran 90 种类参数(mataap 的答案)。real
评论
我将参考 @SteveLionel 最近撰写的这篇启发性文章,并尝试涵盖迄今为止其他答案中没有的一些细节:
- OR 中显示的语法是很久以前编译器提供的常见扩展,当时不同的计算机体系结构开始对整数和实数的内存格式进行不同的设计,其中存储的值的大小(以字节为单位)是。然而,这并没有说明这些值的范围或精度:例如,16位整数的不同实现可以提供不同的范围和限制值。
integer*n
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)
integer(n)
n
12_n
3.4e-2_n
这种解决方案的优点是,除了用于选择类型的查询函数的结果之外,Fortran 没有(现在仍然没有)对数据类型的实现细节做出任何假设,因此代码由正在解决的问题参数化,而不是由语言或硬件参数化。问题在于,正如其他答案中所说,每个编译器都可以选择它们的种类数字,因此假设幻数 like 是不可移植的。
integer(4)
- Fortran 90 还引入了默认种类的概念,即当您不指定种类时会得到什么。
默认类型依赖于实现,尽管在 Fortran 2008 之前,编译器只需要支持一种整数类型和两种实数类型。(在 Fortran 2018 中仍然如此,但增加了一个要求,即至少有一个整数类型支持 18 位十进制数字。如果编写一个不带 kind 说明符的常量文本,则将获得默认 kind。
- 使用 Fortran 2003 和包含的内部模块,您可以查询和选择具有 IEEE 浮点功能的实际类型(如果可用)。
ieee_arithmetic
有些架构同时提供 IEEE 和非 IEEE 浮动类型,例如 HP(以前称为 Compaq,以前称为 DEC)Alpha。在这种情况下,您可以使用内部模块IEEE_ARITHMETIC中的IEEE_SELECTED_REAL_KIND来获取IEEE浮动类型。如果没有满足要求的受支持类型怎么办?在这种情况下,内部函数返回一个负数,该负数将(通常取决于上下文)触发编译时错误。
- 最后,Fortran 2003 引入了内部模块,该模块具有查询编译器实现的类型的存储大小的函数,其内部函数类似于 和 。Fortran 2003 修订版的另一个新增功能是内部模块,它提供了 kind 参数值,以保证在存储、精度和范围方面与 C 类型兼容。
iso_fortran_env
numeric_storage_size
bit_size
iso_c_binding
内部模块 ISO_C_BINDING 声明可与 C 类型互操作的 Fortran 类型的常量,例如 C_FLOAT 和 C_INT。 如果要声明可与 C 互操作的变量和接口,请使用这些变量和接口。
- 最后,我将提到最近的 Fortran 2008 标准,该扩展的内部模块包括命名常量 、 、 m 、 和 ,其值对应于占用规定位数的整数和实数类型。问题在于,这些常量只能保证存储大小,而不是精度或范围。只有在这正是您想要的时才使用它们。
iso_fortran_env
int8
int16
int32
int64
real32
real64
real128
在我看来,这比旧的 *n 扩展好不了多少,因为它告诉你一个类型适合那么多位,但没有其他关于它的东西。例如,有一个编译器,其中 REAL128 以 128 位存储,但实际上是旧的 x86 浮点堆栈寄存器中使用的 80 位“扩展精度”。如果你使用这些,你可能会认为你正在使用一个便携式功能,但实际上你不是,当你得到的那种没有你需要的功能时,你可能会被咬。
评论