我在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
答案 0 :(得分:1)
执行exp(x ** 2.0)
时会出现浮点异常,因为对于单精度浮点数,指数对于x > 9.35
来说太大了。
切换到双精度可以消除溢出。
您还想将x ** 2.0
更改为x**2
,s.t。编译器可以优化整数幂,而不是进行更昂贵的浮点运算。