Function 在Fortran中使用递归函数时出现随机大浮点错误和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

我正在尝试使用b样条曲线和递归函数创建一个箔片截面。问题是,它返回的一些值要么是非常大的浮点数,要么是NaN,有时甚至是无穷大。哪一个值在重新编译后似乎发生了变化,有时由于某种原因比其他值变化更大。它正常返回的值是正确的

有没有人对可能出现的问题有什么建议?非常感谢您的帮助。我知道我的代码很长,但我认为一切都是必要的。首先是程序,然后是带有子程序和函数的模块

正确答案应该是:
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我看到了差异,谢谢!我相应地更改了代码。不过还是一样的行为。