FORTRAN 中关于种类的混淆
Confusion about kinds in FORTRAN
两年多来,我一直在为应用物理问题的数值模拟编写 FORTRAN 代码,并且我尝试遵循 Fortran Best Practices 中描述的约定。
更具体地说,我定义了一个参数为
integer, parameter:: dp=kind(0.d0)
然后将它用于我代码中的所有双打。
但是,我发现(在这个论坛上)如果您使用其他编译器编译您的代码,使用 KIND 参数不一定能提供相同的精度。在 this question 中,我读到一个可能的解决方案是使用 SELECTED_REAL_KIND 和 SELECTED_INT_KIND,据我所知,它们遵循一些约定。
不过,后来我发现了 ISO_FORTRAN_ENV 模块,它定义了 REAL32、REAL64 和 REAL128 KIND 参数。
我想这些确实是可移植的,并且由于它们属于 FORTRAN 2008 标准(尽管 GNU 支持),我想我应该使用它们?
因此,如果有更多知识和经验的人解决我的困惑,我将不胜感激。
此外,我还有一个关于在 HDF5 中使用这些 KIND 的后续问题。我正在使用 H5T_NATIVE_DOUBLE,它确实工作正常(据我所知)但是,in this document 据说这是一个过时的功能,不应使用。相反,他们提供了一个功能
INTEGER(HID_T) FUNCTION h5kind_to_type(kind, flag) RESULT(h5_type) .
当我使用它时,打印出REAL64对应的HID_T整数的确切数值给我50331972,而H5T_NATIVE_DOUBLE给我50331963,这是不同的。
如果我随后尝试使用由 H5kind_to_type 计算的值,HDF5 库运行得很好,并且使用 XDMF,我可以在 VisIt 或 Paraview 中绘制输出而无需修改随附的.xmf 文件。
所以我的第二个问题是(再次):这是正确的用法吗?
类型double precision
和相应的种类kind(1.d0)
在标准中定义得非常好。但它们也不是完全固定的。事实上,历史上有很多计算机使用不同类型的本机格式来表示浮点数,标准必须允许这样做!
因此,double precision
是一种 real
,它比默认的 real
具有更高的精度。默认的real也不是固定的,要对应电脑能用的。
现在我们有了浮点数标准 IEEE_754,它定义了 IEEE 单精度类型 (binary32) 和 IEEE 双精度类型 (binary64) 以及其他一些类型。如果计算机硬件实现了这个标准,几乎所有 20 岁以下的计算机都这样做,编译器很可能选择这两个作为 real
和 double precision
。
Fortran 2008 标准引入了两种常量 real32
和 real64
(以及其他)。它们使您能够请求具有 32 位和 64 位存储大小的真实类型。不能保证它是 IEEE 类型,但在现代计算机上几乎可以肯定。
要请求 IEEE 类型(如果它们可用),请使用模块 ieee_arithmetic
中的内部函数 ieee_selected_real_kind()
。
所有计算机的 IEEE 类型都相同(不包括字节顺序!),但编译器不需要支持它们,因为您的计算机可能在硬件上不支持这些。这只是理论上的可能性,所有现代计算机都支持它们。
现在对于你的 HDF 常量,这些显然只是某些 table 的一些索引,它们是否不同并不重要,重要的是它们是否意味着相同,在你的情况下它们是否相同.
正如我上面所写,在支持 IEEE 754 的计算机上,double precision
极有可能与 IEEE double 相同。它可能不是,如果你使用一些改变这种行为的编译器选项。有一些编译器选项可以将默认 real
提升为双精度,嘿也可以将 double precision
提升为四精度(128 位)以保留标准语义,这需要 double precision
具有更高的精度和存储大小。
结论: 你可以同时使用这两种方法,或者任何其他方式来选择你的种类常量(你也可以使用 iso_c_binding
的 c_float
和 c_double
), 但你应该知道为什么这些方式不同以及它们的实际含义。
两年多来,我一直在为应用物理问题的数值模拟编写 FORTRAN 代码,并且我尝试遵循 Fortran Best Practices 中描述的约定。
更具体地说,我定义了一个参数为
integer, parameter:: dp=kind(0.d0)
然后将它用于我代码中的所有双打。
但是,我发现(在这个论坛上)如果您使用其他编译器编译您的代码,使用 KIND 参数不一定能提供相同的精度。在 this question 中,我读到一个可能的解决方案是使用 SELECTED_REAL_KIND 和 SELECTED_INT_KIND,据我所知,它们遵循一些约定。
不过,后来我发现了 ISO_FORTRAN_ENV 模块,它定义了 REAL32、REAL64 和 REAL128 KIND 参数。
我想这些确实是可移植的,并且由于它们属于 FORTRAN 2008 标准(尽管 GNU 支持),我想我应该使用它们?
因此,如果有更多知识和经验的人解决我的困惑,我将不胜感激。
此外,我还有一个关于在 HDF5 中使用这些 KIND 的后续问题。我正在使用 H5T_NATIVE_DOUBLE,它确实工作正常(据我所知)但是,in this document 据说这是一个过时的功能,不应使用。相反,他们提供了一个功能
INTEGER(HID_T) FUNCTION h5kind_to_type(kind, flag) RESULT(h5_type) .
当我使用它时,打印出REAL64对应的HID_T整数的确切数值给我50331972,而H5T_NATIVE_DOUBLE给我50331963,这是不同的。
如果我随后尝试使用由 H5kind_to_type 计算的值,HDF5 库运行得很好,并且使用 XDMF,我可以在 VisIt 或 Paraview 中绘制输出而无需修改随附的.xmf 文件。
所以我的第二个问题是(再次):这是正确的用法吗?
类型double precision
和相应的种类kind(1.d0)
在标准中定义得非常好。但它们也不是完全固定的。事实上,历史上有很多计算机使用不同类型的本机格式来表示浮点数,标准必须允许这样做!
因此,double precision
是一种 real
,它比默认的 real
具有更高的精度。默认的real也不是固定的,要对应电脑能用的。
现在我们有了浮点数标准 IEEE_754,它定义了 IEEE 单精度类型 (binary32) 和 IEEE 双精度类型 (binary64) 以及其他一些类型。如果计算机硬件实现了这个标准,几乎所有 20 岁以下的计算机都这样做,编译器很可能选择这两个作为 real
和 double precision
。
Fortran 2008 标准引入了两种常量 real32
和 real64
(以及其他)。它们使您能够请求具有 32 位和 64 位存储大小的真实类型。不能保证它是 IEEE 类型,但在现代计算机上几乎可以肯定。
要请求 IEEE 类型(如果它们可用),请使用模块 ieee_arithmetic
中的内部函数 ieee_selected_real_kind()
。
所有计算机的 IEEE 类型都相同(不包括字节顺序!),但编译器不需要支持它们,因为您的计算机可能在硬件上不支持这些。这只是理论上的可能性,所有现代计算机都支持它们。
现在对于你的 HDF 常量,这些显然只是某些 table 的一些索引,它们是否不同并不重要,重要的是它们是否意味着相同,在你的情况下它们是否相同.
正如我上面所写,在支持 IEEE 754 的计算机上,double precision
极有可能与 IEEE double 相同。它可能不是,如果你使用一些改变这种行为的编译器选项。有一些编译器选项可以将默认 real
提升为双精度,嘿也可以将 double precision
提升为四精度(128 位)以保留标准语义,这需要 double precision
具有更高的精度和存储大小。
结论: 你可以同时使用这两种方法,或者任何其他方式来选择你的种类常量(你也可以使用 iso_c_binding
的 c_float
和 c_double
), 但你应该知道为什么这些方式不同以及它们的实际含义。