Fortran数组去重异常:打印B数组整体正确但B(1)结果错误求助
数组去重后单个元素访问异常排查
我有一个包含重复元素的数组A,目标是创建一个与A数据一致但无重复元素的新数组B。执行代码后,打印数组A和B的完整内容能得到预期结果,但单独打印B的第一个元素B(1)时结果不正确,需要协助排查问题。
代码实现
program unique implicit none double precision, dimension(24) :: A = (/0.0d0,0.0d0,0.0d0,0.0d0,& 0.2d0,0.2d0,0.2d0,0.2d0,& 0.4d0,0.4d0,0.4d0,0.4d0,& 0.59d0,0.59d0,0.59d0,0.59d0,& 0.8d0,0.8d0,0.8d0,0.8d0,& 0.1d1,0.1d1,0.1d1,0.1d1/) double precision, dimension(:), allocatable :: B call unique_sub(A,B) print*, 'B =', B print*, 'A(1) = ', A(1) print*, 'B(1) =', B(1) print*, 'size(B)', size(B) contains subroutine unique_sub(A_nonUnique,A_Unique) implicit none double precision, dimension(:), intent(in) :: A_nonUnique double precision, dimension(:), allocatable, intent(out) :: A_Unique logical, dimension(:), allocatable :: mask integer, dimension(:), allocatable :: index_vector integer :: i, n n = size(A_nonUnique) ! 标记重复元素 allocate(mask(n)) mask = .true. do i = n,2,-1 mask(i) = .not.(any(A_nonUnique(i)==A_nonUnique(:i-1))) ! 若当前元素在之前出现过则标记为假 end do ! 生成唯一元素的索引向量 allocate(index_vector, source=pack([(i, i=1,n) ],mask)) ! 复制唯一元素到目标数组 allocate(A_Unique, source=A_nonUnique(index_vector)) print*, 'mask', mask print*, 'index_vector = ', index_vector print*, 'A_nonUnique(index_vector) =', A_nonUnique(index_vector) print*, 'A_Unique =', A_Unique print*, 'A_nonUnique(1) =', A_nonUnique(1) print*, 'A_Unique(1) =', A_Unique(1) end subroutine unique_sub end program unique
运行输出
mask T F F F T F F F T F F F T F F F T F F F T F F F index_vector = 1 5 9 13 17 21 A_nonUnique(index_vector) = 0.0000000000000000 0.20000000000000001 0.40000000000000002 0.58999999999999997 0.80000000000000004 1.0000000000000000 A_Unique = 0.0000000000000000 0.20000000000000001 0.40000000000000002 0.58999999999999997 0.80000000000000004 1.0000000000000000 A_nonUnique(1) = 0.0000000000000000 A_Unique(1) = 0.20000000000000001 B = 0.0000000000000000 0.20000000000000001 0.40000000000000002 0.58999999999999997 0.80000000000000004 1.0000000000000000 A(1) = 0.0000000000000000 B(1) = 0.20000000000000001 size(B) 6
问题分析与解决
从输出可见明显逻辑矛盾:
A_Unique数组整体打印的第一个元素是0.0,但单独打印A_Unique(1)却显示0.2- 主程序中
B数组整体打印正常,但B(1)的输出同样错误
这并非代码逻辑问题(索引向量index_vector第一个元素是1,A_Unique(1)必然等于A_nonUnique(1)=0.0),大概率是Fortran编译器的输出缓存/列表导向打印优化bug:
- 连续使用
print*(列表导向输出)时,部分编译器会出现输出内容错位,尤其是数组打印和单个元素打印连续执行时。 - 旧版本编译器对浮点数的列表输出处理存在异常,导致单个元素的输出被前后内容覆盖或错位。
修复方案
- 使用显式格式输出:替换
print*为带格式的write语句,避免自动格式的错位问题:write(*, '(A, 6F20.16)') 'A_Unique =', A_Unique write(*, '(A, F20.16)') 'A_Unique(1) =', A_Unique(1) - 强制刷新输出缓冲区:在单个元素打印前调用
flush(unit=*),确保缓冲区内容及时输出:flush(unit=*) print*, 'A_Unique(1) =', A_Unique(1) - 升级编译器版本:若使用旧版GCC/GFortran或Intel Fortran,升级到最新稳定版,这类输出bug通常会被修复。
内容的提问来源于stack exchange,提问作者user790082
相关产品推荐
相关产品推荐

