在简单代码上使用F2003进行分段故障

时间:2014-12-11 13:59:34

标签: fortran gfortran

我在F2003中编写了以下代码,试图 实现自适应梯形方法和自适应 辛普森对简单积分的规则方法和我 当我尝试使用代码运行代码时出现seg故障问题 内在函数(exp,log,sin)但它完美适用于 多项式(例如x ** 2)。

我编译得像这样:

$ gfortran -Wall -pedantic -fbounds-check integral_module.f03 integrate.f03 -o integral

我没有收到任何警告。

任何想法??

integral_module.f03

module integral_module
 implicit none
 public :: integral
 !To test which is more efficient
 integer, public :: counter_int = 0, counter_simpson = 0
contains

recursive function integral(f, a, b, tolerance) &
           result(integral_result)

 intrinsic :: abs

 interface
     function f(x) result(f_result)
         real, intent(in) :: x
         real :: f_result
     end function f
 end interface

 real, intent(in) :: a, b, tolerance
 real :: integral_result
 real :: h, mid
 real :: trapezoid_1, trapezoid_2
 real :: left_area, right_area

 counter_int = counter_int + 1

 h = b - a
 mid = (a + b) / 2

 trapezoid_1 = h * (f(a) + f(b)) / 2.0
 trapezoid_2 = h / 2 * (f(a) + f(mid)) / 2.0 + &
               h / 2 * (f(mid) + f(b)) / 2.0

 if(abs(trapezoid_1 - trapezoid_2) < 3.0 * tolerance) then
     integral_result = trapezoid_2
 else
     left_area = integral(f, a, mid, tolerance / 2)
     right_area = integral(f, mid, b, tolerance / 2)
     integral_result = left_area + right_area
 end if

end function integral

recursive function simpson(f, a, h, tolerance) &
          result(simpson_result)

 intrinsic :: abs

 interface
     function f(x) result(f_result)
         real, intent(in) :: x
         real :: f_result
     end function f
 end interface
real, intent(in) :: a, h, tolerance
 real :: simpson_result
 real :: h_half, a_lower, a_upper
 real :: parabola_1, parabola_2
 real :: left_area, right_area

 counter_simpson = counter_simpson + 1

 h_half = h / 2.0
 a_lower = a - h_half
 a_upper = a + h_half

 parabola_1 = h / 3.0 * (f(a - h) + 4.0 * f(a) + f(a + h))

 parabola_2 = h_half / 3.0 * (f(a_lower - h_half) + 4.0 * f(a_lower) + f(a_lower + h_half)) + &
              h_half / 3.0 * (f(a_upper - h_half) + 4.0 * f(a_upper) + f(a_upper + h_half))

 if(abs(parabola_1 - parabola_2) < 15.0 * tolerance) then
     simpson_result = parabola_2
 else
     left_area = simpson(f, a_lower, h_half, tolerance / 2.0)
     right_area = simpson(f, a_upper, h_half, tolerance / 2.0)
     simpson_result = left_area + right_area
 end if

end function simpson

end module integral_module

并且,integration.f03

module function_module
 implicit none
 public :: non_para_errfun, parabola

contains
 function non_para_errfun(x) result(errfun_result)
     real, intent(in) :: x
     real :: errfun_result
     intrinsic :: exp
     errfun_result = exp(x ** 2.0)
 end function non_para_errfun

 function parabola(x) result(parabola_result)
     real, intent(in) :: x
     real :: parabola_result
     parabola_result = x ** 2.0
 end function parabola

 function brainerd(x) result(brainerd_result)
     real, intent(in) :: x
     real :: brainerd_result
     intrinsic :: exp, sin
     brainerd_result = exp(x ** 2.0) + sin(2.0 * x)
 end function brainerd
end module function_module

module math_module
 implicit none
 intrinsic :: atan
 real, parameter, public :: pi = &
       4.0 * atan(1.0)
end module math_module
program integrate

 use function_module,  f => brainerd
 use integral_module
 use math_module, only : pi
 implicit none
 intrinsic :: sqrt, abs

 real :: x_min, x_max, a, h, ans, ans_simpson
 real, parameter :: tolerance = 0.01

 x_min = 0
 x_max = 2.0 * pi
 a = abs(x_max) - abs(x_min)
 h = (abs(x_max) + abs(x_min)) / 2.0
 !ans = integral(f, x_min, x_max, tolerance)
 ans_simpson = simpson(f, a, h, tolerance)

 !print "(a, f11.6)", &
 !      "The integral is approx. ", ans
 print "(a, f11.6)", &
       "The Simpson Integral is approx: ", ans_simpson
 !print "(a, f11.6)", &
 !      "The exact answer is     ", & 
!      1.0/3.0 * x_max ** 3 - 1.0/3.0 * x_min ** 3

 print *

 !print "(a, i5, a)", "The trapezoid rule was executed ", counter_int, " times."
 print "(a, i5, a)", "The Simpson's rule was executed ", counter_simpson, " times."
end program integrate

1 个答案:

答案 0 :(得分:1)

执行exp(x ** 2.0)时会出现浮点异常,因为对于单精度浮点数,指数对于x > 9.35来说太大了。

切换到双精度可以消除溢出。

您还想将x ** 2.0更改为x**2,s.t。编译器可以优化整数幂,而不是进行更昂贵的浮点运算。