You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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:

  1. 连续使用print*(列表导向输出)时,部分编译器会出现输出内容错位,尤其是数组打印和单个元素打印连续执行时。
  2. 旧版本编译器对浮点数的列表输出处理存在异常,导致单个元素的输出被前后内容覆盖或错位。

修复方案

  1. 使用显式格式输出:替换print*为带格式的write语句,避免自动格式的错位问题:
    write(*, '(A, 6F20.16)') 'A_Unique                  =', A_Unique
    write(*, '(A, F20.16)') 'A_Unique(1)    =', A_Unique(1)
    
  2. 强制刷新输出缓冲区:在单个元素打印前调用flush(unit=*),确保缓冲区内容及时输出:
    flush(unit=*)
    print*, 'A_Unique(1)    =', A_Unique(1)
    
  3. 升级编译器版本:若使用旧版GCC/GFortran或Intel Fortran,升级到最新稳定版,这类输出bug通常会被修复。

内容的提问来源于stack exchange,提问作者user790082

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 06:44:58