Fortran多列升序排序代码错误排查求助
Fortran排序代码问题排查与修正
问题概述
编写的Fortran代码读取data.dat数据,将原始数据存入ap(i,4:6),通过矩阵运算得到ap(i,1:3),要求按ap(i,1)升序、ap(i,1)相同则ap(i,2)升序、ap(i,2)仍相同则ap(i,3)升序重排数据,但输出的compare.dat未按预期排序。
代码错误分析
1. 排序条件逻辑错误
在排序的IF条件中(原代码第33行),第三级排序的前置条件写错:
原错误代码片段:
((ap(l,1) < ap(j,1)) .AND. (ap(l,2) == ap(j,2)) .AND. (ap(l,3) < ap(j,3)))
正确逻辑应为当ap(l,1)等于ap(j,1)且ap(l,2)等于ap(j,2)时,才比较ap(l,3),此处误写为ap(l,1) < ap(j,1),直接破坏了三级排序的规则逻辑。
2. 索引数组未同步更新
排序过程中仅对ns(1,:)进行移位操作,但ns(2,:)未同步调整,导致ns数组的两行索引不匹配,后续输出时索引对应关系混乱。
3. 输出逻辑低效且易出错
输出时使用双重循环查找ns(1,j)==i,不仅效率低下,还会因ns数组的错误导致输出顺序混乱,正确做法应直接按排序后的索引顺序输出对应数据行。
修正后的代码
PROGRAM COMPA IMPLICIT NONE INTEGER, PARAMETER :: dp = SELECTED_REAL_KIND(15,14) INTEGER :: i, j, k, l REAL (KIND=dp) :: ap(116,6), lr(3,3), pl(3), ns(2,116) OPEN (UNIT=3, FILE='data.dat', STATUS='OLD') READ (UNIT=3, FMT=*) READ (UNIT=3, FMT=*) DO i = 1, 3, 1 READ (UNIT=3, FMT=*) pl lr(i,:) = pl END DO READ (UNIT=3, FMT=*) DO i = 1, 116, 1 READ (UNIT=3, FMT=*) pl ap(i,4:6) = pl ns(:,i) = i END DO DO i = 1, 116, 1 ap(i,1) = ap(i,4)*lr(1,1)+ap(i,5)*lr(2,1)+ap(i,6)*lr(3,1) ap(i,2) = ap(i,4)*lr(1,2)+ap(i,5)*lr(2,2)+ap(i,6)*lr(3,2) ap(i,3) = ap(i,4)*lr(1,3)+ap(i,5)*lr(2,3)+ap(i,6)*lr(3,3) END DO ! 修正排序条件与索引同步更新 DO i = 2, 116, 1 l = i DO j = 1, i-1, 1 IF ((ap(l,1) < ap(j,1)) .OR. & ((ap(l,1) == ap(j,1)) .AND. (ap(l,2) < ap(j,2))) .OR. & ((ap(l,1) == ap(j,1)) .AND. (ap(l,2) == ap(j,2)) .AND. & (ap(l,3) < ap(j,3)))) THEN ! 同步移动ns的两行 ns(:,j+1:i) = ns(:,j:i-1) ns(:,j) = ns(:,l) l = j END IF END DO END DO OPEN (UNIT=4, FILE='compare.dat', STATUS='UNKNOWN') ! 直接按排序后的索引输出,无需双重循环 DO i = 1, 116, 1 k = INT(ns(1,i)) ! 转换为整数索引 WRITE (UNIT=4, FMT=*) ns(:,i), ap(k,1:3) END DO CLOSE (UNIT=3) CLOSE (UNIT=4) STOP END PROGRAM COMPA
关键修改说明
- 修正排序条件:将第三级排序的前置条件改为
ap(l,1) == ap(j,1),符合三级排序的逻辑规则。 - 同步更新索引数组:移位操作时对
ns(:,j+1:i)进行整体赋值,确保两行索引同步调整。 - 优化输出逻辑:直接通过
ns(1,i)获取排序后的原始数据索引,输出对应ap(k,1:3),避免双重循环的低效与错误。
内容的提问来源于stack exchange,提问作者Kieran
相关产品推荐
相关产品推荐

