我已经在为一个应用物理问题的数值模拟编写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文件。
所以我的第二个问题是(再次):这是正确的用法吗?
答案 0 :(得分:6)
类型double precision
和相应类型kind(1.d0)
完全由标准定义。但它们也没有完全修复。事实上,历史上有许多计算机,并使用不同类型的原生格式作为浮点数,标准必须允许这样!
因此,double precision
是一种real
,其精度高于默认real
。默认的实际也不是固定的,它必须与计算机可以使用的内容相对应。
现在我们有了浮点数IEEE_754的标准,它定义了IEEE单(binary32)和IEEE双类(binary64)以及其他一些。如果计算机硬件实现了这个标准,就像几乎所有20年以下的计算机一样,编译器很可能选择这两个作为real
和double precision
。
Fortran 2008标准带来了两种常量real32
和real64
(以及其他常量)。它们使您能够请求存储大小为32位和64位的实际类型。它不能保证它是IEEE类型,但在现代计算机上几乎可以肯定。
要请求IEEE类型(如果可用),请使用模块ieee_selected_real_kind()
中的内部函数ieee_arithmetic
。
IEEE类型与所有计算机相同(不包括字节序!),但编译器不需要支持它们,因为您可能有一台计算机在硬件中不支持这些。这只是理论上的可能性,所有现代计算机都支持它们。
现在对于你的HDF常数,这些显然只是某些表的某些索引,无论它们是否不同都没关系,重要的是它们是否意味着相同而且在你的情况下它们是这样。
正如我上面所写,在支持IEEE 754的计算机上,double precision
极有可能与IEEE double相同。如果您使用某些更改此行为的编译器选项,则可能不是。有一些编译器选项可以将默认real
提升到两倍,并且hey也可以将double precision
提升为四倍精度(128位)以保留标准语义,这需要double precision
具有更高的精度和存储大小。
结论:您可以使用这两种方式或任何其他方式来选择您的种类常量(您也可以使用iso_c_binding
的{{1}}和c_float
) ,但你应该知道为什么这些方式不同,它们实际意味着什么。