如何将分箱计数结果存入一维数组(Fortran代码优化)
Fortran分箱计数代码优化问题
需求描述
我需要将每个分箱(bin1、bin2、bin3…)的计数结果存入一维数组,当前代码中的if语句过于冗余,急需优化。具体需求是:
- 统计4列数据(b、c、d、e)中数值落在指定区间的次数
- 每个分箱的计数单独存入对应一维数组(如bin1计数存binb数组,bin2存binc数组等)
- 分箱范围统一为-3到3,步长0.3,共20个分箱
- 原本用80个if语句实现了功能,希望通过数组和count函数简化代码
问题现状
参考建议定义了lower和upper数组存储分箱区间,但调用对应索引的区间值时出错,当前代码如下:
program mean_analysis implicit none integer i, j, k, N, l double precision a, b, c, d, e integer binb(1:20),binc(1:20),bind(1:20),bine(1:20) real lower(1:20),upper(1:20) character(100) event upper(1)=-2.7 lower(1)=-3 open(unit = 7, file="zpc_initial_momenta.dat") do l=2,20 lower(l)=lower(l-1)+.3 upper(l)=upper(l-1)+.3 end do do k=1, 10 read(7,'(A)') event do j=1,4000 read(7,*) a, b, c, d, e do i=1,20 binb(i)=binb(i)+count(b>=lower(i:) .and. b<upper(:i)) binc(i)=binc(i)+count(c>=lower(i:) .and. c<upper(:i)) bind(i)=bind(i)+count(d>=lower(i:) .and. d<upper(:i)) bine(i)=bine(i)+count(e>=lower(i:) .and. e<upper(:i)) end do end do end do close(7) open(unit = 8, file="outputanalysis.dat") Write(8,*) 'The bins in each column are as follows:' Write(8,*) 'FIRST COLUMN (MOMENTUM IN X DIRECTION)' write(8,*) binb close(8) end program
问题分析
- count函数用法错误:
lower(i:)和upper(:i)是长度不匹配的数组切片,而当前是单个数值与单个分箱区间比较,不需要用数组切片,直接调用lower(i)和upper(i)即可。 - 分箱计数数组未初始化:Fortran默认不会将整数数组初始化为0,未初始化的binb、binc等数组会包含随机值,导致计数结果错误。
- 分箱区间初始化逻辑冗余:手动设置第一个分箱的上下限容易出错,直接通过循环计算更简洁可靠。
修正后的代码
program mean_analysis implicit none integer i, j, k, l double precision a, b, c, d, e integer binb(1:20), binc(1:20), bind(1:20), bine(1:20) real lower(1:20), upper(1:20) character(100) event ! 初始化所有分箱计数数组为0,避免随机初始值干扰 binb = 0 binc = 0 bind = 0 bine = 0 ! 批量初始化分箱区间:从-3开始,步长0.3,共20个分箱 do l = 1, 20 lower(l) = -3.0 + (l-1)*0.3 upper(l) = lower(l) + 0.3 end do open(unit = 7, file="zpc_initial_momenta.dat") do k = 1, 10 read(7,'(A)') event do j = 1, 4000 read(7,*) a, b, c, d, e ! 遍历每个分箱,判断当前数值是否在区间内并计数 do i = 1, 20 if (b >= lower(i) .and. b < upper(i)) binb(i) = binb(i) + 1 if (c >= lower(i) .and. c < upper(i)) binc(i) = binc(i) + 1 if (d >= lower(i) .and. d < upper(i)) bind(i) = bind(i) + 1 if (e >= lower(i) .and. e < upper(i)) bine(i) = bine(i) + 1 end do end do end do close(7) open(unit = 8, file="outputanalysis.dat") write(8,*) '各列分箱统计结果如下:' write(8,*) '第一列(X方向动量)' write(8,*) binb write(8,*) '第二列(Y方向动量)' write(8,*) binc write(8,*) '第三列(Z方向动量)' write(8,*) bind write(8,*) '第四列(总动量)' write(8,*) bine close(8) end program
优化说明
- 初始化分箱计数数组为0,彻底解决随机初始值导致的计数错误。
- 简化分箱区间初始化逻辑,通过循环直接计算每个分箱的上下限,避免手动设置的误差。
- 替换错误的count函数用法,改用直接的if判断——单个数值与单个区间比较时,这种写法更高效且易读。
- 补充了其他列的输出,让结果更完整。
内容的提问来源于stack exchange,提问作者Garrett Leigh
相关产品推荐
相关产品推荐

