Loops 如何在Fortran中求正弦的泰勒级数
我的目标是找到一个Maclaurin正弦序列,程序返回3个东西:用户提供的角度扩展,精度为10度^⁻15,第一项放弃以获得精度和从函数正弦(x)计算的正弦。这是我的节目:Loops 如何在Fortran中求正弦的泰勒级数,loops,fortran,expansion,trigonometry,Loops,Fortran,Expansion,Trigonometry,我的目标是找到一个Maclaurin正弦序列,程序返回3个东西:用户提供的角度扩展,精度为10度^⁻15,第一项放弃以获得精度和从函数正弦(x)计算的正弦。这是我的节目: program serie de taylor seno implicit none integer*8 N, i, j real*8 serie, x, xrad real*8 xtest, pi
program serie de taylor seno
implicit none
integer*8 N, i, j
real*8 serie, x, xrad
real*8 xtest, pi, senx, func, ten, fat
write(*,*)"Choose en angle in degrees"
read(5,*) x
fat = 1.d0
ten = 10**(-15)
senx = 0.d0
pi= datan2(0.d0,-1.d0)
xrad = (x*pi)/180.d0
xtest = (x*pi)/180.d0
func =dsin(xtest)
i = 0
do while (serie .ge. ten)
do j = 1, 2*i +1
fat = fat*j
end do
N = (2*i)+1
serie = (((-1)**i)*(xrad**N))/fat
senx = senx + serie
i = i + 1
fat = 1
end do
write(*,*)senx
write (*,*) i
write(*,*)func
end program serie de taylor seno
我的问题是do while的循环在任何角度下只运行两次。我做错了什么?总的来说,你的想法是对的,但有几个问题。当尝试这样调试时,您应该在每个循环迭代期间包含详细的输出,以尝试准确跟踪正在发生的事情。我发现的问题是:
- 必须将公差与
的大小进行比较。sin的泰勒级数包含负项,第一个负项导致循环退出(每次都是在第二个负项上)系列
- 您设置的公差实际上为0
只包含整数,因此答案将作为整数计算。使用10**(-15)
,或者更好地使用10.*(15)
1.e-15
- 您的程序名不能有空格,至少对于我版本的
和gfortran
。编辑:显然这是因为我把你的代码复制成了自由形式,谢谢弗朗西斯卡勒斯ifort
- 要确保第一次进入
循环时
,在计算任何系列之前,将
系列定义为某个较大的值
- 不要使用不可移植的种类修饰符,如
。根据系统的不同,您将得到不同的答案。例如,使用real*8
或REAL\u SELECTED\u kind
选择您的种类。因为你要求的是一个给定的容忍度,最好的办法就是要求你真正的容忍度REAL64
- 同样,不要使用
和datan
——相反,使用泛型函数将是一种独立的函数,并将根据给定变量的精度进行计算dsin
- 不要在循环结束时将阶乘设置为
,这需要单独的初始化,只需在循环开始之前将其设置为计算阶乘即可1
- 这里不需要8字节整数
- 仅仅因为最后一项小于公差,并不一定意味着序列收敛于该公差。许多项的总和可能会给你一个问题,尽管这对于快速收敛的sin级数来说可能不是问题
- 单位
通常是标准输入,但并不总是5
将连接到标准输入,或使用read(*,…
中的ISO\u FORTRAN\u ENV
input\u单元
用于什么?它应该是xtest
xtest
- 将不应更改的变量(如pi和公差)设置为参数
- 评论你的代码!它现在不太可读。想想如果你在一年后再看它,你会怎么想。我还保留了我用来检查代码是否正常工作的调试输出。这种输出对初学者很好
program taylor
implicit none
integer, parameter :: wp = selected_real_kind(15,300)
real(wp), parameter :: pi = atan2(0._wp,-1._wp)
real(wp), parameter :: ten = 1.e-15_wp
integer :: N, i, j
real(wp) :: serie, x, xrad
real(wp) :: xtest, senx, func, fat
! -- Initialization
write(*,*) "Choose an angle in degrees"
read(*,*) x
senx = 0._wp
xrad = (x*pi)/180._wp
xtest = (x*pi)/180_wp
func = sin(xtest)
! -- Main loop
i = 0
serie = huge(serie)
do while (abs(serie) .ge. ten)
! -- Compute factorial
fat = 1._wp
do j=1,2*i+1
fat = fat*j
enddo
! -- Evaluate i-th term in series
N = (2*i)+1
serie = (((-1)**i)*(xrad**N))/fat
senx = senx + serie
i = i + 1
write(*,*) 'Completed iteration ', i
write(*,*) 'serie, senx: ', serie, senx
enddo
write(*,*) 'Completed while loop'
write(*,*) 'senx: ', senx
write (*,*) 'i: ', i
write(*,*) 'func: ', func
end program taylor
这为我提供了正确的输出:
mach5% gfortran main.f90 && ./a.out
Choose an angle in degrees
30
Completed iteration 1
serie, senx: 0.52359877559829882 0.52359877559829882
Completed iteration 2
serie, senx: -2.3924596203935038E-002 0.49967417939436376
Completed iteration 3
serie, senx: 3.2795319442867078E-004 0.50000213258879245
Completed iteration 4
serie, senx: -2.1407197692357951E-006 0.49999999186902322
Completed iteration 5
serie, senx: 8.1512566573875745E-009 0.50000000002027989
Completed iteration 6
serie, senx: -2.0315575399030637E-011 0.49999999999996431
Completed iteration 7
serie, senx: 3.5702758612702185E-014 0.50000000000000000
Completed iteration 8
serie, senx: -4.6610066605152958E-017 0.49999999999999994
Completed while loop
senx: 0.49999999999999994
i: 8
func: 0.49999999999999994
关于将整数值赋给实数的最后一个注意事项,如
fat=1.\u wp
。简单地说fat=1
,或fat=1.
,也是一样的。但是,使用相同的表示法(如fat=1.5
)赋给非整数值会失去精度,因此正确的表示法是fat=1.5
。因此我倾向于在所有地方保持我的符号一致,并使用fat=1。wp
为简单起见。我发现了几个问题。首先,什么是dez
?您应该始终使用隐式无
来捕捉这样的错误。对不起,我忘了翻译这个术语,我添加了隐式无,但仍然不起作用serie
在第一次计算循环的条件之前没有定义?以后程序
语句中是否可能有空格取决于它是固定格式的源代码还是自由格式的源代码。准确地说,在Fortran术语中,不必初始化序列
,只需在引用之前定义它即可。@francescalus我已经添加了建议的更改,谢谢!@Ross谢谢,我会记住你的建议,特别是选择的真实种类(,)的使用,如何跟踪循环和我程序的整体组织。关于真实*8和数据2()和dsen(),这是我老师的推荐,因为我将以双精度工作。我稍后会和她谈谈。