回 帖 发 新 帖 刷新版面

主题:[讨论]语句函数对数组赋值出现的一个很奇怪的问题

程序:
 PROGRAM assign_inlinefun2mat
   !
   implicit none
   !
   real,dimension(3) :: m = (/0.2,0.4,0.6/),v
   real :: r
   integer :: i
   !
   !线性内插
   real :: a0,a1,position,interp
   interp(a0,a1,position) = a0*(1.0-position)+a1*position 
   !
   !直接赋值
   v = 0.0
   print*,'----part1----'
   do i = 1,3
     print*,'----start----'
     print*,'v=',v
     print*,'interp(0,1,m(i))=',interp(0,1,m(i))
     v = interp(0,1,m(i))
     print*,'----assign----'
     print*,'v=',v
      print*,'interp(0,1,m(i))=',interp(0,1,m(i))
   end do
   !
   !通过变量间接赋值
   v = 0.0
   print*,'----part2----'
   do i = 1,3
     print*,'----start----'
     print*,'v=',v
     print*,'interp(0,1,m(i))=',interp(0,1,m(i))
     r = interp(0,1,m(i))
     v=r
     print*,'----assign----'
     print*,'v=',v
     print*,'interp(0,1,m(i))=',interp(0,1,m(i))
   end do
   !
 END PROGRAM assign_inlinefun2mat

windows下 CVF 6.5的结果:
[color=FF0000] ----part1----
 ----start----
 v=  0.0000000E+00  0.0000000E+00  0.0000000E+00
 interp(0,1,m(i))=  0.2000000    
 ----assign----
 v=  0.0000000E+00  0.0000000E+00  0.0000000E+00
 interp(0,1,m(i))=  0.2000000    
 ----start----
 v=  0.0000000E+00  0.0000000E+00  0.0000000E+00
 interp(0,1,m(i))=  0.4000000    
 ----assign----
 v=  0.2000000      0.2000000      0.2000000    
 interp(0,1,m(i))=  0.4000000    
 ----start----
 v=  0.2000000      0.2000000      0.2000000    
 interp(0,1,m(i))=  0.6000000    
 ----assign----
 v=  0.4000000      0.4000000      0.4000000    
 interp(0,1,m(i))=  0.6000000    [/color]
 ----part2----
 ----start----
 v=  0.4000000      0.4000000      0.4000000    
 interp(0,1,m(i))=  0.2000000    
 ----assign----
 v=  0.2000000      0.2000000      0.2000000    
 ----start----
 v=  0.2000000      0.2000000      0.2000000    
 interp(0,1,m(i))=  0.4000000    
 ----assign----
 v=  0.4000000      0.4000000      0.4000000    
 ----start----
 v=  0.4000000      0.4000000      0.4000000    
 interp(0,1,m(i))=  0.6000000    
 ----assign----
 v=  0.6000000      0.6000000      0.6000000    

linux下ifort 11.0的结果:
 ----part1----
 ----start----
 v=  0.0000000E+00  0.0000000E+00  0.0000000E+00
 interp(0,1,m(i))=  0.2000000    
 ----assign----
 v=  0.2000000      0.2000000      0.2000000    
 interp(0,1,m(i))=  0.2000000    
 ----start----
 v=  0.2000000      0.2000000      0.2000000    
 interp(0,1,m(i))=  0.4000000    
 ----assign----
 v=  0.4000000      0.4000000      0.4000000    
 interp(0,1,m(i))=  0.4000000    
 ----start----
 v=  0.4000000      0.4000000      0.4000000    
 interp(0,1,m(i))=  0.6000000    
 ----assign----
 v=  0.6000000      0.6000000      0.6000000    
 interp(0,1,m(i))=  0.6000000    
 ----part2----
 ----start----
 v=  0.0000000E+00  0.0000000E+00  0.0000000E+00
 interp(0,1,m(i))=  0.2000000    
 ----assign----
 v=  0.2000000      0.2000000      0.2000000    
 interp(0,1,m(i))=  0.2000000    
 ----start----
 v=  0.2000000      0.2000000      0.2000000    
 interp(0,1,m(i))=  0.4000000    
 ----assign----
 v=  0.4000000      0.4000000      0.4000000    
 interp(0,1,m(i))=  0.4000000    
 ----start----
 v=  0.4000000      0.4000000      0.4000000    
 interp(0,1,m(i))=  0.6000000    
 ----assign----
 v=  0.6000000      0.6000000      0.6000000    
 interp(0,1,m(i))=  0.6000000    


在CVF里直接用语句函数对数组赋值,得到的实际上是上一个循环的结果(结果里红色的部分),如果先把语句函数的结果赋给一个变量,再将该变量赋给数组就没有这个问题,ifort里则不管怎么赋值都没有问题。
本来这样赋值应该算一种错误,不过这个结果实在有些诡异,冒昧的发上来,请各位高手分析下为什么会得到的是上一个循环的值。

回复列表 (共23个回复)

沙发


啥意思?没看明白!
ivf和cvf结果什么区别?
v = interp(0,1,m(i))
这是Fortran对数组的整体操作,相当于做了一个循环,使每个元素的值等于interp(0,1,m(i))。[em1]

板凳


另你说结果有些诡异?哪里诡异?

3 楼

[quote]
v = interp(0,1,m(i))
这是Fortran对数组的整体操作,相当于做了一个循环,使每个元素的值等于interp(0,1,m(i))。[em1][/quote]

对,理论上应该是这个样子,但是CVF里不是这样的,看结果的第一个循环

 ----start----
 v=  0.0000000E+00  0.0000000E+00  0.0000000E+00
 interp(0,1,m(i))=  0.2000000    
 ----assign----
 v=  0.0000000E+00  0.0000000E+00  0.0000000E+00
 interp(0,1,m(i))=  0.2000000  

赋值之前v是0,0,0;interp是0.2。赋值以后v仍然是0,0,0

ifort对应的结果则是“正常”的
 ----start----
 v=  0.0000000E+00  0.0000000E+00  0.0000000E+00
 interp(0,1,m(i))=  0.2000000    
 ----assign----
 v=  0.2000000      0.2000000      0.2000000    
 interp(0,1,m(i))=  0.2000000

4 楼


哦,看到你说的不同的地方了,具体原因不太清楚,或许是cvf的一个bug吧,也许是赋值没有按cvf的规则来。明白原因的出来解释一下,学习学习[em18]

5 楼

不是很明白你的代码, interp(a0,a1,position) 是什么? 为什么里面a0,a1,position都是实数但你用起来好像是数组?
由real :: a0,a1,position,interp, 他不是一个普通实数吗?

6 楼

[quote]不是很明白你的代码, interp(a0,a1,position) 是什么? 为什么里面a0,a1,position都是实数但你用起来好像是数组?
由real :: a0,a1,position,interp, 他不是一个普通实数吗?[/quote]
interp是一个语句函数,功能是插值,插值区间[a0,a1],插值点position。
interp结果是标量,按道理讲v=interp(...)应该将该标量赋给数组v的每一个元素。

我只是解释一下,我也不知道错误出在哪。

7 楼

如果是函数, 那为什么可以"被"赋值呢?
interp(a0,a1,position) = a0*(1.0-position)+a1*position 
而且cvf下这个函数跟ivf下一样? 是以前compaq自带的函数intel继承了?

8 楼

[quote]如果是函数, 那为什么可以"被"赋值呢?
interp(a0,a1,position) = a0*(1.0-position)+a1*position 
而且cvf下这个函数跟ivf下一样? 是以前compaq自带的函数intel继承了?[/quote]
interp是楼主自定义的函数。
跟cvf/ivf/compaq/intel没关系。

9 楼

语句函数的问题基本如ls所说。
其实这相当于定义了一个函数
function interp(a0,a1,position) result(ans)
ans = a0*(1.0-position)+a1*position 
这个功能是fortran本身提供的

说一下新的进展
本来我推测是因为数据类型不同,造成先把上一步的interp赋值给v,后计算当前步interp的错误
不过后来试了一下这样的程序段
     v= 0.0
     print*,'v=',v
     v = interp(0,1,0.2)   
     print*,'v=',v
     v = interp(0,1,0.4)   
     print*,'v=',v
     v = interp(0,1,0.6)   
     print*,'v=',v
结果是正常的
也就是说这种赋值的错误只有在循环里才会出问题,迷茫中……

10 楼

循环体内先对V清零,再赋值试试。

我来回复

您尚未登录,请登录后再回复。点此登录或注册