Function 在Fortran中使用递归函数时出现随机大浮点错误和NaN
我正在尝试使用b样条曲线和递归函数创建一个箔片截面。问题是,它返回的一些值要么是非常大的浮点数,要么是NaN,有时甚至是无穷大。哪一个值在重新编译后似乎发生了变化,有时由于某种原因比其他值变化更大。它正常返回的值是正确的 有没有人对可能出现的问题有什么建议?非常感谢您的帮助。我知道我的代码很长,但我认为一切都是必要的。首先是程序,然后是带有子程序和函数的模块 正确答案应该是:Function 在Fortran中使用递归函数时出现随机大浮点错误和NaN,function,recursion,fortran,fortran90,gfortran,Function,Recursion,Fortran,Fortran90,Gfortran,我正在尝试使用b样条曲线和递归函数创建一个箔片截面。问题是,它返回的一些值要么是非常大的浮点数,要么是NaN,有时甚至是无穷大。哪一个值在重新编译后似乎发生了变化,有时由于某种原因比其他值变化更大。它正常返回的值是正确的 有没有人对可能出现的问题有什么建议?非常感谢您的帮助。我知道我的代码很长,但我认为一切都是必要的。首先是程序,然后是带有子程序和函数的模块 正确答案应该是: xb=0.0147 0.0529 0.1063 0.1675 0.2448 0.3564 0.5202 0.7231 0
xb=0.0147 0.0529 0.1063 0.1675 0.2448
0.3564 0.5202 0.7231 0.9047 1.0000
和
yb=0-0.0088-0.0166-0.0227-0.0264-0.0272-0.0245-0.0178-0.0084-0.0009 0
module splines
IMPLICIT NONE
interface CoxdeBoor
module procedure CoxdeBoor
end interface CoxdeBoor
CONTAINS
SUBROUTINE Splinefoil(N, degree, params, pts, xb, yb)
INTEGER :: degree, N, i, pts
REAL :: Pxb(pts+2), Pyb(pts+2)
REAL :: tegap
REAL, dimension (:):: yb, xb, params
tegap=0.00;
Pxb(1:2)=0
Pyb(1)=0
DO i=1, pts-1
!x-coordinates of bottom
Pxb(i+2)=params(((2*i)-1)+2*pts)
!y-coordinates of bottom
Pyb(i+1)=params(2*i-2+2*pts)
END DO
Pyb(pts+1)=params(4*pts-2)
Pxb(pts+2)=1
Pyb(pts+2)=-0.5*tegap
call Bspline(N,degree,Pxb, Pyb, pts,xb,yb)
END SUBROUTINE Splinefoil
SUBROUTINE Bspline(N, degree, Px, Py, pts, x, y)
INTEGER :: degree, N, j, i, n1, pts, l
INTEGER, parameter :: len=10
REAL :: B(pts+2), Qx(N/2+1), Qy(N/2+1), t(N/2+1), dt
REAL, dimension(1:len) :: T2
REAL, dimension (:):: Px, Py, y, x
n1=pts+1
DO i=1, degree+n1+2
IF (i<(degree+2)) THEN
T2(i)=0
ELSE IF (((degree+2) <= i) .and. (i < (n1 +2))) THEN
T2(i)=(i-degree-1)/real((n1+1-degree))
ELSE
T2(i)=1
END IF
END DO
t(1)=0
dt=1/real((N/2))
DO j=1, N/2
t(j+1)=t(j) + dt
END DO
Qx(1)=0
DO l=1, N/2+1
DO i=0, n1
B(i+1)= CoxdeBoor(degree,i+1, T2,t(l))
x(l)=x(l) + B(i+1) * Px(i+1)
END DO
END DO
DO l=1, N/2+1
DO i=0, n1
B(i+1)= CoxdeBoor(degree,i+1, T2,t(l))
y(l)=y(l) + B(i+1) * Py(i+1)
END DO
END DO
END SUBROUTINE Bspline
RECURSIVE FUNCTION CoxdeBoor(i, j, x, t) result(val)
INTEGER :: i, j, m
REAL :: val, t, t1, t2
REAL, dimension(:) :: x
m=10
IF (i==0) THEN
IF (x(j)<=t .and. t<x(j+1)) THEN
val=1
ELSE IF (x(j)<=t .and. t==x(j+1) .and. x(j+1)==1) THEN
val=1
ELSE
val=0
END IF
ELSE
IF (x(j)<x(j+i)) THEN
t1 =CoxdeBoor(i-1,j,x,t)
val=(t - x(j)) / (x(j+i) - x(j)) * t1
ELSE
val=0
END IF
IF (j<m) THEN
IF (x(j+1)<x(j+i+1)) THEN
t2 =CoxdeBoor(i-1,j+1,x,t)
val=val + (x(j+i+1) - t) / (x(j+i+1) - x(j+1)) * t2
END IF
END IF
END IF
END FUNCTION CoxdeBoor
END MODULE splines
Program TEST
USE splines
implicit none
INTEGER, parameter :: N=20, pts=4
INTEGER :: degree, i
REAL :: params(14), xb(N/2+1), yb(N/2+1), xt(N/2+1), yt(N/2+1), x(N+1), y(N+1)
params=(/0.010021287940814, 0.069234038308141, 0.039810312675194, 0.602154240414724, 0.027370571639440, 0.705186051614965,&
0.015116139770247, -0.010144644178286, 0.119067997228366, -0.028919194962962, 0.338791094291084, -0.028735107857216,&
0.965914604459008, 0.004397962157839/)
degree =3
call Splinefoil(N, degree, params, pts, xt, yt)
write(*,*) xt
write(*,*) yt
OPEN(4, FILE='foil3.dat')
WRITE(4, '(2F10.4)') (xt(i), yt(i), i=1, 11)
CLOSE(4)
END PROGRAM TEST
模样条
隐式无
接口CoxdeBoor
模块程序CoxDebor
端接口CoxdeBoor
包含
子例程Splinefoil(N,度,参数,pts,xb,yb)
整数::度数,N,i,pts
实数:Pxb(pts+2),Pyb(pts+2)
REAL::tegap
实数,维数(:)::yb,xb,参数
tegap=0.00;
Pxb(1:2)=0
Pyb(1)=0
i=1,pts-1吗
!底部的x坐标
Pxb(i+2)=参数((2*i)-1)+2*pts)
!底面y坐标
Pyb(i+1)=参数(2*i-2+2*pts)
结束
Pyb(pts+1)=参数(4*pts-2)
Pxb(pts+2)=1
Pyb(pts+2)=-0.5*tegap
调用Bspline(N、度、Pxb、Pyb、pts、xb、yb)
结束子程序Splinefoil
子例程Bspline(N,度,Px,Py,pts,x,y)
整数::度,N,j,i,n1,pts,l
整数,参数::len=10
实数:B(pts+2),Qx(N/2+1),Qy(N/2+1),t(N/2+1),dt
实数,维数(1:len)::T2
实数,维数(:)::Px,Py,y,x
n1=pts+1
i=1,度+n1+2吗
如果(很抱歉,我偏离了上面有用的注释线程。这是我对这个问题的两分钱-我用gfortran
(使用代码块,并不重要)重新编译了你的代码。我同意启用可用的编译器标志无助于查明问题。最初看起来好像存在绑定检查问题(您指的是数组边界之外的内存块,它没有初始化),但事实并非如此
但是-我为编译器打开了以下标志:
-ffpe-trap=invalid,zero,overflow,underflow,inexact,denormal
在代码块中,您可以在Project>buildoptions>Other Compiler Options
中执行此操作,并手动添加此操作(我想在其他IDE中也会类似)。它所做的是,当遇到错误的浮点操作时(除零、变量类型指定的值范围之外的数字等),会引发错误。这些问题可能会在您的程序中导致任何数量的问题-从显著降低性能(例如,非规范化
,它会中断计算过程,直到CPU找出如何舍入/表示非规范化数字),到给您带来完全错误的结果(0
给您NaN
s)
现在,使用调试工具,您可以在程序中检查并纠正这些错误。有关此标志以及在程序中查找数字错误的其他策略的详细信息,请检查。祝您好运错误查找!如果您忘了在某个地方初始化变量,我猜您可能会在这里找到它,但是在那里有很多工具可以帮助您。首先,您是否使用了编译器运行时检查?(例如,ifort check uninit)你知道每个模块一个隐式none
就足够了吗?另外,使用单元号4
,使用更大的数字也不是一个好主意。如果我正确地阅读了你的代码,调用coxdeboor
的第三个参数是一个10元素的秩1数组,但函数声明它有11个元素。我很可能读入你的代码正确,但您编写它的方式,以及参数数组的显式大小,使得它非常容易受到从数组末尾走出来所引起的错误的影响。您报告的“随机”行为是一个典型的结果。使用假定形状数组要好得多,我认为在许多SO Q和as以及文档中都有详细介绍。是的,只有伪参数可以这样指定。t2
是Bspline
Px
、Py
、x
和y
中的一个局部变量,该子例程中的t2
都可以假定为形状。@francescalus我看到了差异,谢谢!我相应地更改了代码。不过还是一样的行为。