为什么中点法则比辛普森法则更准确;在Fortran上进行黎曼和逼近时的s规则

为什么中点法则比辛普森法则更准确;在Fortran上进行黎曼和逼近时的s规则,fortran,gfortran,Fortran,Gfortran,各位 我只是在用中点法则和辛普森法则计算[1,2]中x^2的积分。我发现,在子区间数相同的情况下,中点规则近似比辛普森规则近似更精确,这真的很奇怪 中点规则近似的源代码是: program midpoint implicit none ! Turn off implicit typing Integer, parameter :: n=100 ! Number of subintervals integer :: i ! Lo

各位

我只是在用中点法则和辛普森法则计算[1,2]中x^2的积分。我发现,在子区间数相同的情况下,中点规则近似比辛普森规则近似更精确,这真的很奇怪

中点规则近似的源代码是:

program midpoint
implicit none                 ! Turn off implicit typing
Integer, parameter :: n=100   ! Number of subintervals
integer :: i                  ! Loop index
real :: xlow=1.0, xhi=2.0     ! Bounds of integral
real :: dx                    ! Variable to hold width of subinterval
real :: sum                   ! Variable to hold sum
real :: xi                    ! Variable to hold location of ith subinterval
real :: fi                    ! Variable to value of function at ith subinterval
dx = (xhi-xlow)/(1.0*n)       ! Calculate with of subinterval
sum = 0.0                     ! Initialize sum
xi = xlow+0.5*dx              ! Initialize value of xi
do i = 1,n,1                  ! Initiate loop
 ! xi = xlow+(0.5+1.0*i)*dx
 write(*,*) "i,xi ",i,xi      ! Print intermidiate result
 fi = xi**2                   ! Evaluate function at ith point
 sum = sum+fi*dx              ! Accumulate sum
 xi = xi+dx                   ! Increment location of ith point
end do                        ! Terminate loop
write(*,*) "sum =",sum
stop                          ! Stop execution of the program
end program midpoint
  ......                   .....      ..................  
 i,xi          100   1.99499905    
 sum =   2.33332348 
program simpson
implicit none                 ! Turn off implicit typing
integer, parameter :: n=100   ! Number of subintervals
integer :: i=0                ! Loop index
real :: xlow=1.0, xhi=2.0     ! Bounds of integral
real :: h                     ! Variable to hold width of subinterval
real :: sum                   ! Variable to hold sum
real :: xi                    ! Variable to hold location of ith subinterval
real :: fi                    ! Variable to value of function at ith subinterval
real :: Psimp                 ! Variable of simpson polynomial of xi interval
h = (xhi-xlow)/(1.0*n)        ! Calculate width of subinterval
sum = 0.0                     ! Initialize sum
do while (xi<=xhi-h)          ! Initiate loop
 xi = xlow+i*2.0*h            ! Increment of xi
 i=i+1
 write(*,*) "i,xi ",i,xi      ! Print intermidiate result
 Psimp=xi**2+4.0*(xi+h)**2+(xi+2.0*h)**2
                              ! Evaluate function at ith point
 sum = sum+(h/3.0)*Psimp      ! Accumulate sum
end do                        ! Terminate loop
write(*,*) "sum =",sum
end program simpson
 ........                  ......    ...................  
 i,xi          101   2.00000000    
 sum =   2.37353396 
相应的执行是:

program midpoint
implicit none                 ! Turn off implicit typing
Integer, parameter :: n=100   ! Number of subintervals
integer :: i                  ! Loop index
real :: xlow=1.0, xhi=2.0     ! Bounds of integral
real :: dx                    ! Variable to hold width of subinterval
real :: sum                   ! Variable to hold sum
real :: xi                    ! Variable to hold location of ith subinterval
real :: fi                    ! Variable to value of function at ith subinterval
dx = (xhi-xlow)/(1.0*n)       ! Calculate with of subinterval
sum = 0.0                     ! Initialize sum
xi = xlow+0.5*dx              ! Initialize value of xi
do i = 1,n,1                  ! Initiate loop
 ! xi = xlow+(0.5+1.0*i)*dx
 write(*,*) "i,xi ",i,xi      ! Print intermidiate result
 fi = xi**2                   ! Evaluate function at ith point
 sum = sum+fi*dx              ! Accumulate sum
 xi = xi+dx                   ! Increment location of ith point
end do                        ! Terminate loop
write(*,*) "sum =",sum
stop                          ! Stop execution of the program
end program midpoint
  ......                   .....      ..................  
 i,xi          100   1.99499905    
 sum =   2.33332348 
program simpson
implicit none                 ! Turn off implicit typing
integer, parameter :: n=100   ! Number of subintervals
integer :: i=0                ! Loop index
real :: xlow=1.0, xhi=2.0     ! Bounds of integral
real :: h                     ! Variable to hold width of subinterval
real :: sum                   ! Variable to hold sum
real :: xi                    ! Variable to hold location of ith subinterval
real :: fi                    ! Variable to value of function at ith subinterval
real :: Psimp                 ! Variable of simpson polynomial of xi interval
h = (xhi-xlow)/(1.0*n)        ! Calculate width of subinterval
sum = 0.0                     ! Initialize sum
do while (xi<=xhi-h)          ! Initiate loop
 xi = xlow+i*2.0*h            ! Increment of xi
 i=i+1
 write(*,*) "i,xi ",i,xi      ! Print intermidiate result
 Psimp=xi**2+4.0*(xi+h)**2+(xi+2.0*h)**2
                              ! Evaluate function at ith point
 sum = sum+(h/3.0)*Psimp      ! Accumulate sum
end do                        ! Terminate loop
write(*,*) "sum =",sum
end program simpson
 ........                  ......    ...................  
 i,xi          101   2.00000000    
 sum =   2.37353396 
辛普森规则近似的源代码是:

program midpoint
implicit none                 ! Turn off implicit typing
Integer, parameter :: n=100   ! Number of subintervals
integer :: i                  ! Loop index
real :: xlow=1.0, xhi=2.0     ! Bounds of integral
real :: dx                    ! Variable to hold width of subinterval
real :: sum                   ! Variable to hold sum
real :: xi                    ! Variable to hold location of ith subinterval
real :: fi                    ! Variable to value of function at ith subinterval
dx = (xhi-xlow)/(1.0*n)       ! Calculate with of subinterval
sum = 0.0                     ! Initialize sum
xi = xlow+0.5*dx              ! Initialize value of xi
do i = 1,n,1                  ! Initiate loop
 ! xi = xlow+(0.5+1.0*i)*dx
 write(*,*) "i,xi ",i,xi      ! Print intermidiate result
 fi = xi**2                   ! Evaluate function at ith point
 sum = sum+fi*dx              ! Accumulate sum
 xi = xi+dx                   ! Increment location of ith point
end do                        ! Terminate loop
write(*,*) "sum =",sum
stop                          ! Stop execution of the program
end program midpoint
  ......                   .....      ..................  
 i,xi          100   1.99499905    
 sum =   2.33332348 
program simpson
implicit none                 ! Turn off implicit typing
integer, parameter :: n=100   ! Number of subintervals
integer :: i=0                ! Loop index
real :: xlow=1.0, xhi=2.0     ! Bounds of integral
real :: h                     ! Variable to hold width of subinterval
real :: sum                   ! Variable to hold sum
real :: xi                    ! Variable to hold location of ith subinterval
real :: fi                    ! Variable to value of function at ith subinterval
real :: Psimp                 ! Variable of simpson polynomial of xi interval
h = (xhi-xlow)/(1.0*n)        ! Calculate width of subinterval
sum = 0.0                     ! Initialize sum
do while (xi<=xhi-h)          ! Initiate loop
 xi = xlow+i*2.0*h            ! Increment of xi
 i=i+1
 write(*,*) "i,xi ",i,xi      ! Print intermidiate result
 Psimp=xi**2+4.0*(xi+h)**2+(xi+2.0*h)**2
                              ! Evaluate function at ith point
 sum = sum+(h/3.0)*Psimp      ! Accumulate sum
end do                        ! Terminate loop
write(*,*) "sum =",sum
end program simpson
 ........                  ......    ...................  
 i,xi          101   2.00000000    
 sum =   2.37353396 
为了获得与中点结果相同的数字精度,我必须将辛普森程序中的子区间数设置为100000,这是中点程序的1000倍(我最初将两个子区间数都设置为100)

我检查了辛普森程序中的代码,没有发现有什么问题


如果我没记错的话,辛普森规则的收敛速度应该比中点规则更快。

克雷格·伯雷曾经说过,一个
循环一旦违反循环的前提,循环就会立即退出。这里,当
x=xhi
时,违反了循环的前提,但循环在该点没有中断,只有当另一个完整的迭代完成并且测试可以应用于循环的顶部时。您可以更一致地使用Fortran习惯用法将循环转换为计数的
DO
循环

DO i = 0, n/2-1
然后评论出

  i=i+1
线路。或者在修改
xi
后立即测试循环前提:

xi = xlow+i*2.0*h ! Increment of xi
if(xi>xhi-h) exit ! Test loop premise

任何一种方法都可以得到辛普森规则中不高于3次多项式的精确结果。

请编辑您的问题并将代码放入代码块。哇,这确实有效!在我之前的辛普森规则程序中,它似乎会做一个额外的循环,它不在积分区间[1,2]。我发现,通过增加子区间的数量(即n=100000),这个“意外的额外”或“剩余”将限制为0,最终会收敛到积分的精确值(7/3)。但我想知道做太多的循环会让自动四舍五入建立。