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
相关产品推荐
相关产品推荐

