Fortran:整数*4 vs 整数(4) vs 整数(kind=4)

发布于 2024-09-08 05:37:03 字数 167 浏览 1 评论 0原文

我正在尝试学习 Fortran,并且看到了很多不同的定义,我想知道他们是否正在尝试完成同样的事情。以下有什么区别?

  • 整数*4
  • 整数(4)
  • 整数(kind=4)

I'm trying to learn Fortran and I'm seeing a lot of different definitions being passed around and I'm wondering if they're trying to accomplish the same thing. What is the difference between the following?

  • integer*4
  • integer(4)
  • integer(kind=4)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

一场信仰旅途 2024-09-15 05:37:03

在 Fortran >=90 中,最好的方法是使用内部函数来指定所需的精度——这既保证了可移植性,又保证了您获得所需的精度。例如,要获取支持至少 8 位十进制数字的整数 imy_int,您可以使用:

integer, parameter :: RegInt_K = selected_int_kind (8)
integer (kind=RegInt_K) :: i, my_int

定义了 RegInt_K (或任何名称)当您选择)作为参数时,您可以在整个代码中将其用作符号。这也使得改变精度变得容易。

请求 8 或 9 位十进制数字通常会获得 4 字节整数。

integer*4 是一个常见的扩展,可追溯到旧版 FORTRAN,用于指定 4 字节整数。尽管如此,这种语法现在不是、也从来不是标准的 Fortran。

integer (4)integer (RegInt_K)integer (kind=4)integer (kind=RegInt_K)< /代码>。 integer (4)integer*4 不同,并且不可移植——语言标准没有指定种类的数值。大多数编译器使用 kind=4 表示 4 字节整数 - 对于这些编译器,integer*4integer(4) 将提供相同的整数类型——但也有例外,因此 integer(4) 是不可移植的,最好避免使用。

实数的方法类似。

更新:如果您不想按所需精度指定数字类型,而是按它们将使用的存储来指定,Fortran 2008 提供了一种方法。实数和整数可以通过使用ISO_FORTRAN_ENV模块后的存储位数来指定,例如,对于 4 字节(32 位)整数

use ISO_FORTRAN_ENV
integer (int32) :: MyInt

: gfortran 手册在“内在模块”下有文档。

In Fortran >=90, the best approach is use intrinsic functions to specify the precision you need -- this guarantees both portability and that you get the precision that you need. For example, to obtain integers i and my_int that will support at least 8 decimal digits, you could use:

integer, parameter :: RegInt_K = selected_int_kind (8)
integer (kind=RegInt_K) :: i, my_int

Having defined RegInt_K (or whatever name you select) as a parameter, you can use it throughout your code as a symbol. This also makes it easy to change the precision.

Requesting 8 or 9 decimal digits will typically obtain a 4-byte integer.

integer*4 is an common extension going back to old FORTRAN to specify a 4-byte integer. Although, this syntax isn't and was never standard Fortran.

integer (4) or integer (RegInt_K) are short for integer (kind=4) or integer (kind=RegInt_K). integer (4) is not the same as integer*4 and is non-portable -- the language standard does not specify the numeric values of kinds. Most compilers use the kind=4 for 4-byte integers -- for these compilers integer*4 and integer(4) will provide the same integer type -- but there are exceptions, so integer(4) is non-portable and best avoided.

The approach for reals is similar.

UPDATE: if you don't want to specify numeric types by the required precision, but instead by the storage that they will use, Fortran 2008 provides a method. reals and integers can be specified by the number of bits of storage after useing the ISO_FORTRAN_ENV module, for example, for a 4-byte (32-bit) integer:

use ISO_FORTRAN_ENV
integer (int32) :: MyInt

The gfortran manual has documentation under "intrinsic modules".

娜些时光,永不杰束 2024-09-15 05:37:03

只是一个更明确的解释是什么类型。编译器有一个不同数值类型的表。所有整数类型都是基本类型的不同种类——整数。假设编译器有 1 字节、2 字节、4 字节、8 字节和 16 字节整数(或实数)类型。在表中,编译器对每种类型都有一个索引——该索引是类型号。

许多编译器选择此编号:

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的答案)。

Just one more explicit explanation what the kind is. The compiler has a table of different numerical types. All integer types are different kinds of the basic type -- integer. Let's say the compiler has 1 byte, 2 byte, 4 byte, 8 byte and 16 byte integer (or real) kinds. In the table the compiler has an index to each of this kind -- this index is the kind number.

Many compilers choose this numbering:

kind number    number of bytes
1              1
2              2
4              4
8              8
16             16

But they can choose any other numbering. One of the obvious possibilities is

kind number    number of bytes
1              1
2              2
3              4
4              8
5              16

There are indeed compilers (at least g77 and NAG) which choose this approach. There are also options to change this. Therefore kind numbers are not portable integer(kind=4) or integer(4) means a 4 byte integer or a 8-bytes integer depending on the compiler.

integer*4 is portable in the sense it always means 4 bytes. But on the other hand it is not portable because it has never been part of any standard. Programs using this notation are not valid Fortran 77, 90 or any other Fortran.

To see the right options how to set the kind numbers see M.S.B.'s answer.

The same concept holds for real data types. See Fortran 90 kind parameter (the mataap's answer).

街角卖回忆 2024-09-15 05:37:03

我将参考这个启发性的内容文章,最近由 @SteveLionel 撰写,并尝试涵盖迄今为止其他答案中未出现的一些细节:


  1. integer*nreal*n< 中显示的语法/code> 是很久以前编译器提供的常见扩展,当时不同的计算机体系结构开始对整数和实数值的内存格式有不同的设计,其中 n存储值的字节数。然而,这并没有说明这些值的范围或精度:例如,16 位整数的不同实现可以提供不同的范围和极限值。

寄存器大小可以是 8、12、16、30、32、36、48、60 或 64 位,一些 CDC 机器有补码整数(允许整数负零!),PDP-11 系列有根据系列,有几种不同的浮点格式,IBM 360/370 对其浮点进行了“十六进制标准化”,等等 [...] 这些扩展如此受欢迎,以至于许多程序员认为(甚至今天许多人认为)这种语法是标准的 Fortran;事实并非如此!


  1. 当 Fortran 90 发布时,kind 参数以及内在查询函数(特别是 kindselected_int_kind 和 < code>selected_real_kind,还有其他,如 precisiondigitsepsilon...)来帮助程序员指定最小对数字类型的精度和范围的要求(仍然没有正式提及存储模型或字节)。语法为 integer(kind=n) 甚至 integer(n),其中 n 是与支持的整数类型相对应的常量值由编译器。对于文字常量,语法为 12_n3.4e-2_n

    这个解决方案的优点是,除了用于选择类型的查询函数的结果之外,Fortran 没有(现在仍然没有)对数据类型的实现细节做出任何假设,因此代码是由要解决的问题来参数化,而不是由语言或硬件来参数化。正如其他答案中所述,问题是每个编译器都可以选择自己的类型数字,因此假设像 integer(4) 这样的幻数不可移植。


  1. Fortran 90 还引入了默认类型的概念,这就是当您不指定类型时所得到的。

默认类型与实现相关,但在 Fortran 2008 之前,编译器只需要支持一种整数类型和两种实数类型。 (在 Fortran 2018 中仍然如此,但有一个附加要求,即至少一种整数类型支持 18 位十进制数字。)如果编写不带类型说明符的常量文字,则会获得默认类型。


  1. 借助 Fortran 2003 以及内置模块 ieee_arithmetic,您可以查询并选择具有 IEEE 浮点功能的实数类型(如果可用)。

有些架构同时支持 IEEE 和非 IEEE 浮点类型,例如 HP(以前称为 Compaq,以前称为 DEC)Alpha。在这种情况下,您可以使用内部模块 IEEE_ARITHMETIC 中的 IEEE_SELECTED_REAL_KIND 来获取 IEEE 浮点类型。如果没有符合要求的支持类型怎么办?在这种情况下,内在函数返回一个负数,这将(通常取决于上下文)触发编译时错误。


  1. 最后,Fortran 2003 引入了 iso_fortran_env 内部模块,该模块具有查询编译器实现的类型存储大小的功能,以及诸如 numeric_storage_size 之类的内部函数> 和 bit_size。 Fortran 2003 修订版的另一个新增内容是 iso_c_binding 内部模块,它提供种类参数值以保证在存储、精度和范围方面与 C 类型的兼容性。

内部模块 ISO_C_BINDING 声明可与 C 类型互操作的 Fortran 类型常量,例如 C_FLOAT 和 C_INT。如果您要声明可与 C 互操作的变量和接口,请使用它们。


  1. 最后,我将提到最近的 Fortran 2008 标准,该标准扩展了内部模块 iso_fortran_env 以包含命名常量 int8,int16int32m int64real32real64real128,其值对应于占用指定位数的整数类型和实数类型。问题是这些常量仅保证存储大小,而不是精度或范围。仅当这正是您想要的时才使用它们。

在我看来,这比旧的 *n 扩展好不了多少,因为它告诉您一个类型适合那么多位,但除此之外什么也没有。举个例子,有一个编译器,其中 REAL128 以 128 位存储,但实际上是旧 x86 浮点堆栈寄存器中使用的 80 位“扩展精度”实数。如果您使用这些功能,您可能会认为自己正在使用便携式功能,但实际上并非如此,并且当您获得的功能不具备您所需的功能时,可能会被咬伤。

I will make reference to this enlightening article, wrote recently by @SteveLionel, and try cover some details that are not present in the other answers so far:


  1. The syntax shown in integer*n or real*n was a common extension provided by compilers long time ago, when different computer architectures started to have different designs for in-memory format of integer and real values, where n was the size in bytes of the value stored. However, that said nothing about range or precision of those values: different implementations of a 16bit integer, for example, could provide different ranges and limit values.

Register sizes could be 8, 12, 16, 30, 32, 36, 48, 60 or 64 bits, some CDC machines had ones-complement integers (allowing minus zero for an integer!), the PDP-11 line had several different floating point formats depending on the series, the IBM 360/370 had "hex normalization" for its floating point, etc [...] So popular were these extensions that many programmers thought (and even today many think) that this syntax is standard Fortran; it isn't!


  1. When Fortran 90 came out, kind parameters were added to the language, along with intrinsic inquiry functions (specially kind, selected_int_kind and selected_real_kind, but also others, like precision, digits, epsilon...) to aid the programmer to specify minimun requirements for precision and range of numeric types (still, no official mention to storage model or bytes). The syntax is integer(kind=n) or even integer(n), where n is a constant value corresponding to a kind of integer supported by the compiler. For literal constants, the syntax is 12_n or 3.4e-2_n.

    The advantage of this solution was that Fortran didn't (and still don't) make any assumptions about the implementation details of data-types other than the results of the inquiry functions used to choose the type, so the code is parameterized by the problem being solved, not by the language or the hardware. The gotcha is, as said in other answers, each compiler can choose their kind numbers, thus assuming magic number like integer(4) is not portable.


  1. Also with Fortran 90 came the concept of default kinds, that is what you get when you don't specify a kind.

The default kinds were implementation dependent, though up through Fortran 2008 a compiler was required to support only one integer kind and two real kinds. (That's still true in Fortran 2018, but there's an added requirement that at least one integer kind support 18 decimal digits.) If you write a constant literal without a kind specifier, you got the default kind.


  1. With Fortran 2003 and the inclusion of the intrinsic module ieee_arithmetic, you can inquire and select a real type with IEEE floating point capabilities, if avaliable.

There are architectures where both IEEE and non-IEEE floating types are available, such as the HP (formerly Compaq formerly DEC) Alpha. In this case you can use IEEE_SELECTED_REAL_KIND from intrinsic module IEEE_ARITHMETIC to get an IEEE floating kind. And what if there is no supported kind that meets the requirements? In that case the intrinsics return a negative number which will (usually, depending on context) trigger a compile-time error.


  1. Finally, Fortran 2003 brought the iso_fortran_env intrinsic module, that had functions to inquire the storage size of the types implemented by a compiler, with intrinsics like numeric_storage_size and bit_size. Another addition of Fortran 2003 revision was the iso_c_binding intrinsic module, that provided kind parameter values to guarantee compatibility with C types, in storage, precision and range.

Intrinsic module ISO_C_BINDING declares constants for Fortran types that are interoperable with C types, for example C_FLOAT and C_INT. Use these if you're declaring variables and interfaces interoperable with C.


  1. As a final note, I will mention the recent Fortran 2008 Standard, that extended intrinsic module iso_fortran_env to include named constants int8, int16, int32m int64, real32, real64 and real128, whose values correspond to the kinds of integer and real kinds that occupy the stated number of bits. The gotcha is that those constants only assure storage size, not precision or range. Only use them when this is exactly what you want.

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文