Floating point fortran中的数据类型不匹配

Floating point fortran中的数据类型不匹配,floating-point,gradient,double-precision,fortran95,Floating Point,Gradient,Double Precision,Fortran95,我已经用Fortran 95编写了一个基本算法,用中心差分加上一个称为Richardson外推的过程来计算函数的梯度(代码中规定了一个例子) function f(n,x) ! The scalar multivariable function to be differentiated integer :: n real(kind = kind(1d0)) :: x(n), f f = x(1)**5.d0 + cos(x(2)) + log(x(3)) - sqrt(x(4)) end

我已经用Fortran 95编写了一个基本算法,用中心差分加上一个称为Richardson外推的过程来计算函数的梯度(代码中规定了一个例子)

function f(n,x)
! The scalar multivariable function to be differentiated

integer :: n
real(kind = kind(1d0)) :: x(n), f

f = x(1)**5.d0 + cos(x(2)) + log(x(3)) - sqrt(x(4))

end function f
!=====!
!=====!
!=====!

program gradient
!==============================================================================!
! Calculates the gradient of the scalar function f at x=0using a finite        !
! difference approximation, with a low order Richardson extrapolation.         !
!==============================================================================!

parameter (n = 4, M = 25)
real(kind = kind(1d0)) :: x(n), xhup(n), xhdown(n), d(M), r(M), dfdxi, h0, h, gradf(n)

h0 = 1.d0
x  = 3.d0

! Loop through each component of the vector x and calculate the appropriate
! derivative
do i = 1,n
! Reset step size
h = h0

    ! Carry out M successive central difference approximations of the derivative
do j = 1,M
        xhup = x
        xhdown = x
        xhup(i) = xhup(i) + h
        xhdown(i) = xhdown(i) - h
        d(j) = ( f(n,xhup) - f(n,xhdown) ) / (2.d0*h)
    h = h / 2.d0
    end do

    r = 0.d0
    do k = 3,M      r(k) = ( 64.d0*d(k) - 20.d0*d(k-1) + d(k-2) ) / 45.d0
        if ( abs(r(k) - r(k-1)) < 0.0001d0 ) then
        dfdxi = r(k)
            exit
        end if
    end do

    gradf(i) = dfdxi
end do

! Print out the gradient
write(*,*) " "
write(*,*) " Grad(f(x)) = "
write(*,*) " "
do i = 1,n
    write(*,*) gradf(i)
end do

end program gradient

正在产生类型不匹配
real(4)/real(8)
。我尝试了几种不同的双精度声明,在代码中添加了每个适当的双精度常量,并使用
d0
,每次都会得到相同的错误。对于函数
f
如何可能产生一个单精度数字,我有点困惑。

问题是,f在主程序中没有明确定义,因此它被隐式地假定为单精度,这是gfortran的real(4)类型

我完全同意High Performance Mark的意见,即您确实应该在所有fortran代码中使用
implicit none
,以确保所有对象都被明确声明。通过这种方式,您将获得一条关于未明确定义f的更合适的错误消息

也可以考虑两件事:

  • 在模块内定义函数,并在主程序中导入该模块。最好只在模块内定义所有子例程/函数,这样编译器在调用函数时可以对参数的数量和类型进行额外检查

  • 您可以(同样在模块中)为精度引入一个常数,并在任何地方使用它,其中必须指定实数的种类。以下面的示例为例,仅更改行

    integer, parameter :: dp = kind(1.0d0)
    
    进入

    您可以将所有实变量从双精度更改为单精度。还要注意文字常量的
    \u dp
    后缀,而不是
    d0
    后缀,这也会自动调整它们的精度

    module accuracy
      implicit none
    
      integer, parameter :: dp = kind(1.0d0)
    
    end module accuracy
    
    
    module myfunc
      use accuracy
      implicit none
    
    contains
    
      function f(n,x)
        integer :: n
        real(dp) :: x(n), f
        f = 0.5_dp * x(1)**5 + cos(x(2)) + log(x(3)) - sqrt(x(4))
      end function f
    
    end module myfunc
    
    
    program gradient
      use myfunc
      implicit none
    
      real(dp) :: x(n), xhup(n), xhdown(n), d(M), r(M), dfdxi, h0, h, gradf(n)
      :
    
    end program gradient
    

我甚至不会尝试调试Fortran代码,因为它不会在每个范围内声明
隐式none
。我建议您增强代码,并在完成后编辑问题。非常感谢,这就解决了我的问题。我知道在Fortran中使用
implicit none
是一种很好的做法,但从Matlab的背景来看,这是我必须习惯的,有时也不使用。
integer, parameter :: dp = kind(1.0)
module accuracy
  implicit none

  integer, parameter :: dp = kind(1.0d0)

end module accuracy


module myfunc
  use accuracy
  implicit none

contains

  function f(n,x)
    integer :: n
    real(dp) :: x(n), f
    f = 0.5_dp * x(1)**5 + cos(x(2)) + log(x(3)) - sqrt(x(4))
  end function f

end module myfunc


program gradient
  use myfunc
  implicit none

  real(dp) :: x(n), xhup(n), xhdown(n), d(M), r(M), dfdxi, h0, h, gradf(n)
  :

end program gradient