Fortran中count内禀函数报错:mask参数需为逻辑数组的解决方法
问题描述
尝试用count函数精简Fortran程序以提升效率,但编译时每条count语句均报错:
Error: 'mask' argument of 'count' intrinsic at (1) must be a logical array
目标是统计b、c、d、e四列动量在20个指定区间内的数量,当前程序代码如下:
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(1:20) close(8) end program
解决建议
count函数误用问题
Fortran的count函数要求mask参数是逻辑数组,但你这里的b>=lower(i).and. b<upper(i)是单个逻辑标量(因为b是标量,和单个区间边界比较),完全不需要用count。直接把逻辑值转换为整数即可——Fortran中.true.等价于1,.false.等价于0,替换写法如下:
binb(i)=binb(i)+int(b>=lower(i).and. b<upper(i))
也可以用merge函数明确指定值:
binb(i)=binb(i)+merge(1, 0, b>=lower(i).and. b<upper(i))
- 未初始化计数数组
binb、binc、bind、bine数组未初始化,初始值是内存随机垃圾值,会导致统计结果完全错误。添加初始化语句:
! 初始化计数数组为0 binb = 0 binc = 0 bind = 0 bine = 0
- 精度匹配问题
lower和upper是real类型,而b/c/d/e是double precision类型,混合精度比较可能导致精度损失。建议统一精度,把lower和upper改为double precision,同时赋值时使用双精度字面量:
double precision lower(1:20),upper(1:20) ! 设置区间边界(双精度) upper(1) = -2.7d0 lower(1) = -3d0 do l=2,20 lower(l) = lower(l-1) + 0.3d0 upper(l) = upper(l-1) + 0.3d0 end do
- 优化循环结构(可选)
当前三重循环(k→j→i)可以调整,比如先把所有数据读入数组再一次性统计,但对于你的需求,修改后的标量处理已经足够高效。
修改后的完整代码示例
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) double precision lower(1:20),upper(1:20) character(100) event ! 初始化计数数组为0 binb = 0 binc = 0 bind = 0 bine = 0 ! 设置区间边界(双精度) upper(1) = -2.7d0 lower(1) = -3d0 do l=2,20 lower(l) = lower(l-1) + 0.3d0 upper(l) = upper(l-1) + 0.3d0 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 binb(i) = binb(i) + int(b>=lower(i) .and. b<upper(i)) binc(i) = binc(i) + int(c>=lower(i) .and. c<upper(i)) bind(i) = bind(i) + int(d>=lower(i) .and. d<upper(i)) bine(i) = bine(i) + int(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(1:20) Write(8,*) 'SECOND COLUMN (MOMENTUM IN Y DIRECTION)' write(8,*) binc(1:20) Write(8,*) 'THIRD COLUMN (MOMENTUM IN Z DIRECTION)' write(8,*) bind(1:20) Write(8,*) 'FOURTH COLUMN (ENERGY)' write(8,*) bine(1:20) close(8) end program
内容的提问来源于stack exchange,提问作者Garrett Leigh
相关产品推荐
相关产品推荐

