Fortran77 删除重复行
delete duplicate rows in Fortran77
我有一个 table 的文件,包含 119 列(以空格分隔)和大约 50000 行(行)。我想删除重复的条目,即那些具有所有相同列 (119) 的行。我草拟了这段代码:
PROGRAM deldup
IMPLICIT NONE
DOUBLE PRECISION PAR(119),PAR2(119)
INTEGER I,J,K,LINE,TREP
CHARACTER filename*40
c Get the input file name
CALL getarg(1,filename)
c File where the results will be stored.
OPEN(29, FILE="result.dat", STATUS='UNKNOWN')
c Current line number
LINE=0
c counting repeated points
TREP=0
101 LINE=LINE+1
OPEN(27, FILE=filename, STATUS='OLD')
c Verifying that we are not in the first line... and we read the
c corresponding one
IF (LINE.NE.1) THEN
DO K=1,LINE-1
READ(27,11,ERR=103,END=9999)
END DO
ENDIF
READ(27,11,ERR=103,END=9999) (PAR(I),I=1,119)
c Start comparing line by line looking for matches. If a match is
c found , close the
c file and open it again to read the next line. If the end of file is
c reached and not iqual rows found, write the line in "results.dat"
102 READ(27, 11,END=104, ERR=102) (PAR2(I),I=1,119)
DO J=1,119
IF ( PAR(J).NE.PAR2(J) ) THEN
GOTO 102
ELSEIF (J.EQ.119) THEN
TREP=TREP+1
GOTO 103
ENDIF
END DO
104 WRITE(29,11) (PAR(I),I=1,119)
103 CLOSE(27)
GOTO 101
9999 WRITE(*,*) "DONE!,", TREP, "duplicated points found!"
CLOSE(27)
CLOSE(28)
CLOSE(29)
11 FORMAT(200E14.6)
END
实际有效的只是超级慢。为什么?有没有我可以使用的图书馆?抱歉我的无知,我是 Fortran77 的新手。
你打开和关闭原始文件的每一行,这非常慢!要加快速度,您可以使用 rewind
。
不过,主要问题是算法的复杂性:O(n^2)
[您将每一行与其他每一行进行比较]。首先,我会保留一个唯一行列表,并与该列表进行比较。如果已列出新行,则丢弃它 - 如果没有,则它是一个新的唯一行。这会将复杂性降低到 O(n*m)
,(希望)m << n
(m 是唯一行的数量)。对行进行排序可能会加快比较速度。
下一句是从 I/O 移到内存中!将完整的文件读入一个数组,或者至少将唯一行的列表保存在内存中。一个 50,000x119 双精度数组需要 ~45MB 的 RAM,所以我认为这应该是可行的 ;-)
在最后一步将结果写回一块。
第一个问题:为什么坚持使用 Fortran 77?自从 g95 和 gfortran 出现以来,没有真正的理由使用一个已经过时了 20 多年的标准。
去重的规范方法是对它们进行排序,去重,然后按原来的顺序输出。如果您使用良好的排序算法,例如快速排序或堆排序,这将为您提供 O(n log n) 性能。
补充说明:将程序中的幻数(如 119)放入 PARAMETER 语句也是一个好主意。
我有一个 table 的文件,包含 119 列(以空格分隔)和大约 50000 行(行)。我想删除重复的条目,即那些具有所有相同列 (119) 的行。我草拟了这段代码:
PROGRAM deldup
IMPLICIT NONE
DOUBLE PRECISION PAR(119),PAR2(119)
INTEGER I,J,K,LINE,TREP
CHARACTER filename*40
c Get the input file name
CALL getarg(1,filename)
c File where the results will be stored.
OPEN(29, FILE="result.dat", STATUS='UNKNOWN')
c Current line number
LINE=0
c counting repeated points
TREP=0
101 LINE=LINE+1
OPEN(27, FILE=filename, STATUS='OLD')
c Verifying that we are not in the first line... and we read the
c corresponding one
IF (LINE.NE.1) THEN
DO K=1,LINE-1
READ(27,11,ERR=103,END=9999)
END DO
ENDIF
READ(27,11,ERR=103,END=9999) (PAR(I),I=1,119)
c Start comparing line by line looking for matches. If a match is
c found , close the
c file and open it again to read the next line. If the end of file is
c reached and not iqual rows found, write the line in "results.dat"
102 READ(27, 11,END=104, ERR=102) (PAR2(I),I=1,119)
DO J=1,119
IF ( PAR(J).NE.PAR2(J) ) THEN
GOTO 102
ELSEIF (J.EQ.119) THEN
TREP=TREP+1
GOTO 103
ENDIF
END DO
104 WRITE(29,11) (PAR(I),I=1,119)
103 CLOSE(27)
GOTO 101
9999 WRITE(*,*) "DONE!,", TREP, "duplicated points found!"
CLOSE(27)
CLOSE(28)
CLOSE(29)
11 FORMAT(200E14.6)
END
实际有效的只是超级慢。为什么?有没有我可以使用的图书馆?抱歉我的无知,我是 Fortran77 的新手。
你打开和关闭原始文件的每一行,这非常慢!要加快速度,您可以使用 rewind
。
不过,主要问题是算法的复杂性:O(n^2)
[您将每一行与其他每一行进行比较]。首先,我会保留一个唯一行列表,并与该列表进行比较。如果已列出新行,则丢弃它 - 如果没有,则它是一个新的唯一行。这会将复杂性降低到 O(n*m)
,(希望)m << n
(m 是唯一行的数量)。对行进行排序可能会加快比较速度。
下一句是从 I/O 移到内存中!将完整的文件读入一个数组,或者至少将唯一行的列表保存在内存中。一个 50,000x119 双精度数组需要 ~45MB 的 RAM,所以我认为这应该是可行的 ;-) 在最后一步将结果写回一块。
第一个问题:为什么坚持使用 Fortran 77?自从 g95 和 gfortran 出现以来,没有真正的理由使用一个已经过时了 20 多年的标准。
去重的规范方法是对它们进行排序,去重,然后按原来的顺序输出。如果您使用良好的排序算法,例如快速排序或堆排序,这将为您提供 O(n log n) 性能。
补充说明:将程序中的幻数(如 119)放入 PARAMETER 语句也是一个好主意。