Fortran Coder

标题: 从顺序文件读取数据用于递归计算,栈堆溢出,求大大指点!!! [打印本页]

作者: McP    时间: 2015-5-17 21:43
标题: 从顺序文件读取数据用于递归计算,栈堆溢出,求大大指点!!!
本帖最后由 McP 于 2015-5-17 21:44 编辑

使用函数子程序读取文件中的数据并代入递归子程序计算,编译无误,运行显示错误为forrtl:severe(170):program exception - stack overflow。
因为这只是测试子程序用的,实际数据量可能更大,猜想是不是应该用直接文件来读取呢(但之前发过贴求助,大大们建议使用顺序文件。)?若用直接文件的话,还望指点如何编程。。。之前就是因为用直接文件失败才改为顺序文件的。。。谢谢诸位大大!!!!!!!
[Fortran] 纯文本查看 复制代码
function P(n) result(Pa)
implicit none
integer::i
integer,intent(in)::n
real::a(1827),b(1827),c(1827),d(1827),e(1827),Pa
open(1,file='et.csv')
read(1,*)
do i=1,1827
    read(1,*)a(i),b(i),c(i),d(i),e(i)
enddo
close(1)
Pa=a(n)
end function

function ET(n) result(ETa)
implicit none
integer::z
integer,intent(in)::n
real::a(1827),b(1827),c(1827),d(1827),e(1827),ETa
open(1,file='et.csv')
read(1,*)
do  z=1,1827
    read(1,*)a(z),b(z),c(z),d(z),e(z)
enddo
close(1)
ETa=a(n)
end function

recursive function th(n) result(tha)
implicit none
real::tha,n,thmax,P,ET
if(n==1)then
        tha=thmax
else
        tha=th(n-1)+P(n-1)-ET(n-1)
endif
if(tha>thmax) tha=thmax
end function

program main
implicit none
integer::n,th
print*,'input n'
read*,n
print*,th(n)
end program main


csv数据文件结构如下
0.432475628753395,0.9,1980,1,1
0.342833411868196,0,1980,1,2
0.774539737844607,0,1980,1,3
0.891810760279446,0,1980,1,4



作者: vvt    时间: 2015-5-17 21:48
我的建议是,先把数据文件里的数据都读出来,放在内存里。(只读一次,而不是每次递归都读一次)

直接文件只适合于每个记录,或每一行长度都一样的情况。你的文件显然不满足。
作者: McP    时间: 2015-5-17 22:28
vvt 发表于 2015-5-17 21:48
我的建议是,先把数据文件里的数据都读出来,放在内存里。(只读一次,而不是每次递归都读一次)

直接文件 ...

请问您的意思是每个数据都用一个变量名存起来这样么?好像有点恐怖啊。。。
因为是第一次做这个量的数据,所以不甚了解,还望赐教!
作者: vvt    时间: 2015-5-18 08:35
用数组啊。

你就说你的文件一共有多少行多少列吧。
作者: McP    时间: 2015-5-18 19:53
vvt 发表于 2015-5-18 08:35
用数组啊。

你就说你的文件一共有多少行多少列吧。

5列,接近20000行
作者: fcode    时间: 2015-5-18 20:39
那 so easy,一共才
5*20000 = 10W个数字,算32位4字节,一共40W个字节,也就是390KB而已。


作者: McP    时间: 2015-5-18 20:44
fcode 发表于 2015-5-18 20:39
那 so easy,一共才
5*20000 = 10W个数字,算32位4字节,一共40W个字节,也就是390KB而已。

恩恩,但现在还有一个比较大的问题,还望大大解惑!
因为希望程序以后能通用,所以要解决不知道数据文件行列数的问题,请问这种情况下还如何定义数组呢?
作者: McP    时间: 2015-5-18 20:57
fcode 发表于 2015-5-18 20:39
那 so easy,一共才
5*20000 = 10W个数字,算32位4字节,一共40W个字节,也就是390KB而已。

个人是认为用直接文件读取在编程上简单些(因为源文件是excel文件,转成若干个只有一列的csv就好了),有些问题还望大大能指教下:之前一直在尝试用函数子程序读取直接文件的某一行作为函数值来计算(迭代),觉得这样会不会就不会有读取顺序文件的栈堆溢出这个情况了。但当时编的都失败了。能不能请大大示范下如何如何写一个function A(n)来实现读取一个只有一列数据的csv(第一行为标题),并使函数值为对应第n行的数值呢?多谢大大指点迷津!(小弟的意思就是不需要每次都读完整个文件再把其中一个值赋给函数,而是每次能直接到对应行去读取)Orz
作者: fcode    时间: 2015-5-18 22:56
第一,未知行数列数
http://fcode.cn/code_gen-34-1.html
参考这个代码。这个代码是获得了行数,和每一行的列数。如果你确定每一行的列数都一样,那么只调用一次就行了。(大多数数据是这样)

第二,不要在迭代中每次都去读取文件,非常慢,效率非常低,低到你不忍直视。
你要理解,文件输入输出,是极慢的。所以,要尽量避免重复的输入输出。(像你每次迭代都重新读一次文件,就非常浪费,非常浪费)

第三,除非文件非常大,一般都一次性读到内存里,当做一个数组(或其他结构)

第四,对文本文件来说,你想直接读取(access="direct")某个数据,前提是每一行的长度是一样的,这样编译器可以通过每行长度*行数直接定位到第N行。否则,不要去试图用循环的方式去“直接”读取。(理由同第二条)
作者: McP    时间: 2015-5-19 16:59
fcode 发表于 2015-5-18 22:56
第一,未知行数列数
http://fcode.cn/code_gen-34-1.html
参考这个代码。这个代码是获得了行数,和每一行的 ...

谢谢大大指点!
我还是老实用数组了。。。Orz




欢迎光临 Fortran Coder (http://bbs.fcode.cn/) Powered by Discuz! X3.2