Fortran2018类最优编写方案:Fortran77子例程转写代码评审
Fortran77转Fortran2018实现方案与优化建议
现有代码核心问题梳理
- 计算函数
find_bin_nobin内每次调用都分配x%bin数组,既会造成内存泄漏,也没有完成数组赋值逻辑,运行时会读取无效值 - 循环逻辑和原F77代码完全相反,原代码是
er>0时继续减数组元素,现有代码er<=0时才进入循环,计算结果完全错误 - 原公共块的
bini数组属于全局固定参数,不应该在计算函数中处理内存,应该在类型实例初始化阶段完成分配和赋值 - 变量
dble转换冗余,你已经定义了统一精度pr,直接用real(var, pr)做精度转换更统一 - 函数
intent属性错误,计算过程不需要修改类型成员,x的属性应该为intent(in)
数组处理解决方案
- 给
Find_bin类型新增初始化子程序,专门接收外部传入的bini数组,完成内部bin数组的内存分配与数值拷贝,完全替代原公共块的作用 - 移除计算函数中的内存分配逻辑,仅保留核心计算逻辑,和内存操作解耦
- 新增数组边界校验逻辑,避免输入参数不合法导致的数组越界问题
完整优化后代码
module precision implicit none public integer, parameter :: pr = selected_real_kind(12,300) integer, parameter :: ir = selected_int_kind(9) ! 替换硬编码的4,兼容性更好 end module precision module constants use precision implicit none public real(pr), parameter :: zero = 0.0_pr real(pr), parameter :: one = 1.0_pr real(pr), parameter :: four = 4.0_pr real(pr), parameter :: pi = four * atan(one) end module constants module class_Dntrnpr use precision use constants, only : zero, one implicit none private public :: BinFinder type :: BinFinder private real(pr) :: e integer(ir) :: j real(pr), allocatable :: bin(:) contains procedure :: init => bin_finder_init procedure :: get_bin => find_bin_nobin final :: bin_finder_final end type BinFinder contains ! 类型初始化子程序:传入e、起始索引j、bin数组 subroutine bin_finder_init(this, e, j, bini_arr) class(BinFinder), intent(out) :: this real(pr), intent(in) :: e integer(ir), intent(in) :: j real(pr), intent(in) :: bini_arr(:) this%e = e this%j = j ! 分配内存并拷贝数组数值 allocate(this%bin(size(bini_arr)), source = bini_arr) end subroutine bin_finder_init ! 核心计算函数:逻辑和原F77完全对齐 function find_bin_nobin(this) result(f) class(BinFinder), intent(in) :: this real(pr) :: f, f1, er integer(ir) :: i, n n = size(this%bin) er = this%e i = this%j ! 边界校验 if (this%j > n) then f = er / this%bin(n) return end if ! 和原F77 do 100循环逻辑完全对齐 do i = this%j, n er = er - this%bin(i) if (er <= zero) exit end do if (er > zero) then ! 循环走完er仍大于0,对应原代码100 continue之后的逻辑 f1 = er / this%bin(n) f = real(n + 1, pr) + f1 - real(this%j, pr) else ! 提前退出循环,对应原代码200行逻辑 f = real(i - this%j, pr) + er / this%bin(i) + one end if end function find_bin_nobin ! 类型析构子程序:自动释放内存 subroutine bin_finder_final(this) type(BinFinder), intent(inout) :: this if (allocated(this%bin)) deallocate(this%bin) end subroutine bin_finder_final end module class_Dntrnpr program test use class_Dntrnpr use precision implicit none integer(ir), parameter :: nbmax = 40 real(pr) :: bini(nbmax) type(BinFinder) :: en real(pr) :: res ! 初始化bin数组 bini = 1.0_pr ! 初始化类型实例 call en%init(e = 2.0_pr, j = 1_ir, bini_arr = bini) ! 计算bin值 res = en%get_bin() write(*,*) "计算结果为:", res end program test
代码规范优化建议
- 类型成员默认设为private,仅通过暴露的接口操作,避免外部随意修改内部状态出错
- 硬编码的精度参数替换为
selected_int_kind/selected_real_kind返回值,跨编译器兼容性更好 - 核心计算函数逻辑完全对齐原F77代码,增加边界校验避免非法输入崩溃
- 增加final析构子程序自动释放数组内存,不需要手动管理避免泄漏
- 命名语义化,比如
Find_bin改为BinFinder,函数名改为get_bin,代码可读性大幅提升 - 可根据需求给
get_bin函数增加elemental属性,支持批量传入数组参数计算,适配向量化场景
内容的提问来源于stack exchange,提问作者mytmarco
相关产品推荐
相关产品推荐

