【问题标题】:Parameter precision in fortranfortran 中的参数精度
【发布时间】:2018-08-28 23:06:23
【问题描述】:

我使用的是 intel fortran 2016。我定义了一些精度变量如下:

 ! definition of single, double and quad precision
        integer, parameter :: SINGLE_PRECISION = selected_real_kind(6, 37)
        integer, parameter :: DOUBLE_PRECISION = selected_real_kind(15, 307) ! is used as standard precision
        integer, parameter :: QUAD_PRECISION = selected_real_kind(33, 4931)

        ! definition of variable precision for REAL, INTEGER
        integer, parameter :: REAL_TYPE = DOUBLE_PRECISION
        integer, parameter :: INTEGER_TYPE = 4

我现在想使用这些来控制在子例程中声明的参数的精度,如下所示:

  SUBROUTINE SKIP(IUNIT,NBYTS)

  IMPLICIT DOUBLE PRECISION (A-H,O-Z)
  Character c*1
  Parameter(n1 = 1024, nT1 = 8*n1)

我尝试了以下方法:

Parameter(INTEGER_TYPE)((n1 = 1024, nT1 = 8*n1)
Parameter(INTEGER_TYPE)((n1 = 1024, nT1 = 8*n1, kind = INTEGER_TYPE)

一切都无济于事。在 Fortran 中定义参数精度的正确方法是什么?

谢谢

【问题讨论】:

  • 如果您将现代 Fortran 与种类一起使用,请不要使用隐式类型和参数语句。只需在一个语句中定义参数的类型和值,如下面的答案所示(与您定义自己的种类参数的方式完全相同)。并使用 IMPLICIT NONE,它可以为您节省数小时甚至数天的调试时间。

标签: fortran


【解决方案1】:

注意:这与Francescalus' answer 基本相同,但有一些额外的绒毛。

这里的问题与IMPLICIT 声明有关。

Fortran standard 发表以下声明:

5.5 隐式陈述

  1. 在作用域单元中,IMPLICIT 语句指定类型,并且 可能是类型参数,对于所有隐式类型的数据实体,其 名称以语句中指定的字母之一开头。 或者,它可能表明没有隐式类型规则 适用于特定的范围单元。

  2. <snip>

  3. 在每个作用域单元中,都有一个映射,可能为空,在 每个字母 A, B, ..., Z 和一个类型(和类型参数)。 IMPLICIT 语句指定其中字母的映射 字母规格列表。 IMPLICIT NONE 指定所有的空映射 这些信。如果没有为字母指定映射,则 程序单元或接口主体的默认值是默认整数,如果 字母为I, J、...或N,否则默认为真实,并且 内部或模块过程的默认值是主机中的映射 范围单位。

简而言之,默认情况下,所有内容都是默认类型REAL,除非它以IJ、...、N 开头,那么它的类型默认为INTEGER

在问题的示例中,变量n1nT1 因此默认为INTEGER,除非另有说明。因此,以下可能是一个解决方案:

subroutine skip(IUNIT,NBYTS)
   implicit double precision (A-H,O-Z)
   character c*1
   integer(kind=integer_kind), parameter :: n1 = 1024, nT1 = 8*n1
   ...
end subroutine skip

作为对变量声明的一般评论,我想发表以下评论:

  • 默认使用implicit none。它使调试更容易
  • 避免使用星号,它不是字符标准的一部分,而且对于字符来说,它被宣布为过时。
  • 使用在内部模块iso_fortran_env 中声明的kind 参数
  • 请注意,double precision 并不一定意味着字面或 IEEE 意义上的“双精度”。这只是意味着,两倍于real 的存储空间和比real 更高的精度。 (更高的精度可能是一位数)。

【讨论】:

    【解决方案2】:

    你可以定义一个特定类型的参数

    TYPE, PARAMETER :: name = value_kind
    

    所以要定义一个整数 n1,类型为 INTEGER_TYPE

    integer(kind=INTEGER_TYPE), parameter :: n1 = 1024_INTEGER_TYPE
    

    【讨论】:

      【解决方案3】:

      您有一个答案,它给出了指定命名常量类型的最佳方法。您可以在 this question 周围找到更多详细信息。

      不过,我将添加一些关于 parameter 语句的细节。

      parameter 语句使对象成为命名常量并指定其值。它没有指定该对象的类型或种类。

      问题示例对n1nT1 使用了隐式类型。这些是隐式默认整数。

      隐式规则可能会改变(我不会展示如何),但类型也可以显式给出:

      integer(INTEGER_TYPE) n1, nT1
      parameter (n1=1024, nT1=8*n1)
      

      不过,其他答案的形式更可取。而且,正如那里所指出的,如果需要,也可以在 parameter 语句中给出文字常量的种类。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2010-12-04
        • 2017-01-06
        • 1970-01-01
        • 1970-01-01
        • 2012-04-18
        • 2014-04-17
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多