You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Fortran 95接口参数类型不匹配:如何支持自定义精度?

Fortran 95中实现自定义精度的过程参数传递问题

此前已经明确,将子过程作为参数传递给另一子过程时必须使用显式接口,但当前遇到精度不匹配的编译错误:示例中sub1使用双精度real(8),而sub2默认使用单精度real(4),导致参数类型不匹配。以下是具体代码、编译命令及错误信息,以及Fortran 95下的解决办法。

代码文件

main.f90

program main
    use mod1, only : sub1
    use mod2, only : sub2
    implicit none

    real :: a, b

    a = 0.2
    
    call sub2(sub1, a, b)

    print *, b, exp(sqrt(a))
end program main

mod1.f90

module mod1
    implicit none

    public sub1
    
contains
    subroutine sub1(arg1,  arg2)
        real(8), intent(in) :: arg1
        real(8), intent(out) ::  arg2

        arg2 = sqrt(arg1)
    end subroutine sub1
end module mod1

mod2.f90

module mod2
    implicit none

    public sub2    
contains
    subroutine sub2(other_sub, arg1,  arg2)
        interface
            subroutine other_sub(arg1,  arg2)
                real, intent(in) :: arg1
                real, intent(out) :: arg2
            end subroutine other_sub
        end interface
        real, intent(in) :: arg1
        real, intent(inout) :: arg2

        call other_sub(arg1, arg2)
        arg2 = exp(arg2)
    end subroutine sub2
end module mod2

编译命令

$ gfortran -c mod1.f90 mod2.f90 -std=f95
$ gfortran mod1.o mod2.o main.f90 -std=f95

错误信息

main.f90:10:14:

   10 |     call sub2(sub1, a, b)
      |              1
Error: Interface mismatch in dummy procedure ‘other_sub’ at (1): Type mismatch in argument 'arg1' (REAL(4)/REAL(8))

解决办法

在Fortran 95中,可以通过统一精度参数+泛型接口的方式实现自定义精度选择,具体步骤如下:

1. 创建精度定义模块

新建mod_precision.f90,定义单/双精度的kind参数,方便统一管理:

module mod_precision
    implicit none
    ! 单精度(对应REAL(4))
    integer, parameter :: sp = kind(1.0)
    ! 双精度(对应REAL(8))
    integer, parameter :: dp = kind(1.0d0)
end module mod_precision

2. 修改mod1,使用统一精度参数

让sub1基于精度模块的参数定义类型,确保精度可配置:

module mod1
    use mod_precision, only : dp
    implicit none

    public sub1
    
contains
    subroutine sub1(arg1, arg2)
        real(dp), intent(in) :: arg1
        real(dp), intent(out) :: arg2

        arg2 = sqrt(arg1)
    end subroutine sub1
end module mod1

3. 修改mod2,实现泛型接口支持多精度

为sub2创建单精度和双精度两个版本,通过泛型接口自动匹配调用时的精度:

module mod2
    use mod_precision, only : sp, dp
    implicit none

    public sub2

    ! 定义抽象接口,规范不同精度子过程的参数格式
    abstract interface
        subroutine real_sub(arg1, arg2)
            import :: sp
            real(sp), intent(in) :: arg1
            real(sp), intent(out) :: arg2
        end subroutine real_sub

        subroutine dbl_sub(arg1, arg2)
            import :: dp
            real(dp), intent(in) :: arg1
            real(dp), intent(out) :: arg2
        end subroutine dbl_sub
    end interface

contains
    ! 单精度版本的sub2
    subroutine sub2_sp(other_sub, arg1, arg2)
        procedure(real_sub) :: other_sub
        real(sp), intent(in) :: arg1
        real(sp), intent(inout) :: arg2

        call other_sub(arg1, arg2)
        arg2 = exp(arg2)
    end subroutine sub2_sp

    ! 双精度版本的sub2
    subroutine sub2_dp(other_sub, arg1, arg2)
        procedure(dbl_sub) :: other_sub
        real(dp), intent(in) :: arg1
        real(dp), intent(inout) :: arg2

        call other_sub(arg1, arg2)
        arg2 = exp(arg2)
    end subroutine sub2_dp

    ! 泛型接口,自动匹配调用时的精度类型
    interface sub2
        module procedure sub2_sp, sub2_dp
    end interface

end module mod2

4. 修改主程序,指定使用的精度

在main.f90中引入精度模块,将变量声明为对应精度类型:

program main
    use mod_precision, only : dp
    use mod1, only : sub1
    use mod2, only : sub2
    implicit none

    real(dp) :: a, b

    a = 0.2_dp
    
    call sub2(sub1, a, b)

    print *, b, exp(sqrt(a))
end program main

编译运行

执行以下命令编译,即可正常运行:

$ gfortran -c mod_precision.f90 mod1.f90 mod2.f90 -std=f95
$ gfortran mod_precision.o mod1.o mod2.o main.f90 -std=f95
$ ./a.out

如果需要切换为单精度,只需将mod1中的dp改为sp,主程序中的变量类型也改为real(sp)即可。

内容的提问来源于stack exchange,提问作者jared

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 17:37:33