Fortran Coder

查看: 1681|回复: 4
打印 上一主题 下一主题

[通用算法] 数据排序

[复制链接]

68

帖子

25

主题

0

精华

专家

F 币
321 元
贡献
197 点
跳转到指定楼层
楼主
发表于 2023-6-16 09:55:32 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 Kieran 于 2023-6-19 10:15 编辑

大家好,

我有一个数据文件。内容如下。
[Fortran] 纯文本查看 复制代码
         116
Parameter
   0.2951429939E+02    0.0000000000E+00    0.0000000000E+00
   0.0000000000E+00    0.1500000000E+02    0.0000000000E+00
   0.0000000000E+00   0.0000000000E+00   0.2510000038E+02
Parameter
   0.000000000    0.500000000    0.300000012
   0.041669998    0.500000000    0.328289986
   0.041669998    0.500000000    0.384860009
   0.000000000    0.500000000    0.413150012
   0.000000000    0.500000000    0.469720006
   0.041669998    0.500000000    0.498010010
   0.041669998    0.500000000    0.554579973
   0.000000000    0.500000000    0.582870007
   0.083329998    0.500000000    0.300000012
   0.125000000    0.500000000    0.328289986
   0.125000000    0.500000000    0.384860009
   0.083329998    0.500000000    0.413150012
   0.083329998    0.500000000    0.469720006
   0.125000000    0.500000000    0.498010010
。。。。。。
我想重排各行的位置。重排标准是,先按每行中的第一数据,由小到达排列。如果有两行,或者多行的第一个数据相等,则按第二个数据由小到大重排这些行的位置。如果有两行,或者多行第二个数据也相等,则按第三个数据重排各行位置。
这是我的代码。
[Fortran] 纯文本查看 复制代码
PROGRAM COMPAIMPLICIT 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
   DO j = 1, i-1, 1
      IF ((ap(i,1) < ap(j,1)) .OR. &
         ((ap(i,1) == ap(j,1)) .AND. (ap(i,2) < ap(j,2))) .OR. &
         ((ap(i,1) < ap(j,1)) .AND. (ap(i,2) == ap(j,2)) .AND. &
         (ap(i,3) < ap(j,3)))) THEN
         k = ns(1,i)
         DO l = j, i-1, 1
            ns(1,l+1) = ns(1,l)
         END DO
         ns(1,j) = k
      END IF
   END DO
END DO

OPEN (UNIT=4, FILE='compare.dat', STATUS='UNKNOWN')
DO i = 1, 116, 1
   DO j = 1, 116, 1
      IF (ns(1,j) == i) WRITE (UNIT=4, FMT=*) ns(:,j), ap(j,1:3)
   END DO
END DO

CLOSE (UNIT=3)
CLOSE (UNIT=4)
STOP
END PROGRAM COMPA

运行后,输出的重排结果如下。
[Fortran] 纯文本查看 复制代码
    1.0000000000000000        1.0000000000000000        0.0000000000000000        7.5000000000000000        7.5300004152000044        91.000000000000000        3.0000000000000000        1.2298607965527013        7.5000000000000000        9.6599863721468040     
   91.000000000000000        4.0000000000000000        0.0000000000000000        7.5000000000000000        10.370065458197006     
   91.000000000000000        5.0000000000000000        0.0000000000000000        7.5000000000000000        11.789972329093603     
   91.000000000000000        6.0000000000000000        1.2298607965527013        7.5000000000000000        12.500051440243805     
   91.000000000000000        7.0000000000000000        1.2298607965527013        7.5000000000000000        13.919957533040389     
   91.000000000000000        8.0000000000000000        0.0000000000000000        7.5000000000000000        14.630037397190604     
   91.000000000000000        9.0000000000000000        2.4594265091401013        7.5000000000000000        7.5300004152000044     
   92.000000000000000        2.0000000000000000        1.2298607965527013        7.5000000000000000        8.2400787733501950     
   93.000000000000000        11.000000000000000        3.6892874237500002        7.5000000000000000        9.6599863721468040
。。。。。。
很显然,这个排序时错误的,但我没找到程序里的错误。能麻烦大家帮我看下,我的代码哪里出了错误码?谢谢。


谢谢。


分享到:  微信微信
收藏收藏 点赞点赞 点踩点踩

250

帖子

2

主题

0

精华

宗师

F 币
1731 元
贡献
872 点

规矩勋章

沙发
发表于 2023-6-20 10:02:11 | 只看该作者
你的意思是不是用数组ns保存排序的序号,我大概修改了一下
[Fortran] 纯文本查看 复制代码
! nline=116
DO i = 1, nline-1
  write(*,'(2i4)')i;
  ins=ns(1,i); ! 数组排序序号,原始序号在ns(2,i)中
   DO j = i+1, nline
      jns=ns(1,j); ! 序号
      IF ((ap(jns,1) < ap(ins,1)) .OR. &
         ((abs(ap(jns,1)-ap(ins,1))<1.0e-6) .AND. (ap(jns,2) < ap(ins,2))) .OR. &
         ((abs(ap(jns,1)-ap(ins,1))<1.0e-6) .AND. (abs(ap(jns,2)-ap(ins,2))<1.0e-6) .AND. (ap(jns,3) < ap(ins,3))) & ! TODO: 原来是<
         ) THEN
         write(*,*)'swap ',i,j
         ns(1,i) = jns
         ns(1,j)=ins
         ins=jns
         cycle;
      END IF
   END DO
END DO

OPEN (UNIT=4, FILE='resu.txt')
DO i = 1, nline
   WRITE (UNIT=4, FMT='(2i6,2x,10(f12.4,2x))') ns(1:2,i), ap(ns(1,i),1:3)
END DO

68

帖子

25

主题

0

精华

专家

F 币
321 元
贡献
197 点
板凳
 楼主| 发表于 2023-6-20 11:55:15 | 只看该作者
本帖最后由 Kieran 于 2023-6-20 12:06 编辑
necrohan 发表于 2023-6-20 10:02
你的意思是不是用数组ns保存排序的序号,我大概修改了一下
[mw_shl_code=fortran,true]
! nline=116

非常感谢你的回复。

我的代码确实是在用ns变量保存各行在排序后的新序号。

我想请教几个问题。

1.你的代码的比较方式,是将各行中”最小“的那一行放在序号变量ns中的最前面,然后再放第二小的,紧接着是第三小,第四小。。。以此类推。我的理解正确吗?

2.请问你的代码中的CYCLE命令作用是什么呢?可不可以不用这个命令呢?

3.请问你觉得我的代码中哪里出了错误呢?我一直没找到原因。

谢谢,望指教。

250

帖子

2

主题

0

精华

宗师

F 币
1731 元
贡献
872 点

规矩勋章

地板
发表于 2023-6-20 15:06:12 | 只看该作者
Kieran 发表于 2023-6-20 11:55
非常感谢你的回复。

我的代码确实是在用ns变量保存各行在排序后的新序号。

1、我能大概明白你的代码的意思,但是排序那里和我思路不一样,我参考你的方式按自己的思路写的,结果就是你说的那样,从小到大排列。
2、cycle是直接进行下一次循环,不执行endif后面的语句节省点时间,这里因为endif后面没有语句了,所以不用也可以。
3、如果读入的lr是单位矩阵,那么你的代码ap(i,1:3)和ap(i,4:6)是相同的,我是这么测试查看输出结果的。
你的代码我没太明白,但是31行那个ap(i,1)<ap(j,1)应该是==。
我印象中浮点数比较用==的容易出问题,我用的绝对值差判断。
你的代码34~36行我不明白为什么要对ns循环赋值,我理解ns数组保存的序号,直接调换就行。
输出排序结果那段循环,就是43~47行,我不明白一共就116行你为什么要嵌套2次,直接循环116次输出就行。

68

帖子

25

主题

0

精华

专家

F 币
321 元
贡献
197 点
5#
 楼主| 发表于 2023-6-20 15:16:59 | 只看该作者
necrohan 发表于 2023-6-20 15:06
1、我能大概明白你的代码的意思,但是排序那里和我思路不一样,我参考你的方式按自己的思路写的,结果就 ...

谢谢你的回复和指点。

我原本想着用insertion sorting方法排序,但我可能自己没想清楚每个步骤,所以代码不合理。

我再仔细想想吧。

再次感谢。
您需要登录后才可以回帖 登录 | 极速注册

本版积分规则

捐赠本站|Archiver|关于我们 About Us|小黑屋|Fcode ( 京ICP备18005632-2号 )

GMT+8, 2024-11-22 05:04

Powered by Tencent X3.4

© 2013-2024 Tencent

快速回复 返回顶部 返回列表