python 的 cos x 展开的泰勒级数
Taylor series of cos x expansion in python
我想计算 cosx 系列的总和(同时保持 x 为弧度)。这是我创建的代码:
import math
def cosine(x,n):
sum = 0
for i in range(0, n+1):
sum += ((-1) ** i) * (x**(2*i)/math.factorial(2*i))
return sum
我使用 math.cos()
检查了它。
当我尝试小数字时它工作得很好:
print("Result: ", cosine(25, 1000))
print(math.cos(25))
输出:
Result: 0.991203540954667
0.9912028118634736
数量还是差不多。但是当我尝试更大的数字时,即 40,它只是 returns 一个完全不同的值。
Result: 1.2101433786727471
-0.6669380616522619
有人知道为什么会这样吗?
离展开点越远,泰勒展开的误差项就越大(在本例中,x_0 = 0
)。为了减少错误,通过仅在区间 [0, 2 * pi]
:
内评估来利用周期性和对称性
def cosine(x, n):
x = x % (2 * pi)
total = 0
for i in range(0, n + 1):
total += ((-1) ** i) * (x**(2*i) / math.factorial(2*i))
return total
这可以进一步改进为[0, pi/2]
:
def cosine(x, n):
x = x % (2 * pi)
if x > pi:
x = abs(x - 2 * pi)
if x > pi / 2:
return -cosine(pi - x, n)
total = 0
for i in range(0, n + 1):
total += ((-1) ** i) * (x**(2*i) / math.factorial(2*i))
return total
与您得到的答案相反,无论参数有多大,这个泰勒级数都会收敛。项的分母中的阶乘最终使项变为 0。
但是在阶乘部分占主导地位之前,项的绝对值会越来越大。本机浮点数没有足够的精度位来保留足够的信息以供 low-order 位生存。
这是一种不会丢失任何精度的方法。它不实用,因为它很慢。相信我,我告诉你通常需要多年的经验才能学习如何编写实用、快速、high-quality 的数学库。
def mycos(x, nbits=100):
from fractions import Fraction
x2 = - Fraction(x) ** 2
i = 0
ntries = 0
total = term = Fraction(1)
while True:
ntries += 1
term = term * x2 / ((i+1) * (i+2))
i += 2
total += term
if (total // term).bit_length() > nbits:
break
print("converged to >=", nbits, "bits in", ntries, "steps")
return total
然后是你的例子:
>>> mycos(25)
converged to >= 100 bits in 60 steps
Fraction(177990265631575526901628601372315751766446600474817729598222950654891626294219622069090604398951917221057277891721367319419730580721270980180746700236766890453804854224688235663001, 179569976498504495450560473003158183053487302118823494306831203428122565348395374375382001784940465248260677204774780370309486592538808596156541689164857386103160689754560975077376)
>>> float(_)
0.9912028118634736
>>> mycos(40)
converged to >= 100 bits in 82 steps
Fraction(-41233919211296161511135381283308676089648279169136751860454289528820133116589076773613997242520904406094665861260732939711116309156993591792484104028113938044669594105655847220120785239949370429999292710446188633097549, 61825710035417531603549955214086485841025011572115538227516711699374454340823156388422475359453342009385198763106309156353690402915353642606997057282914587362557451641312842461463803518046090463931513882368034080863251)
>>> float(_)
-0.6669380616522619
注意事项:
full-precision 结果需要很多位。
四舍五入为浮点数,它们与您从 math.cos()
.
得到的完全一致
不需要接近 1000 步就可以收敛。
我想计算 cosx 系列的总和(同时保持 x 为弧度)。这是我创建的代码:
import math
def cosine(x,n):
sum = 0
for i in range(0, n+1):
sum += ((-1) ** i) * (x**(2*i)/math.factorial(2*i))
return sum
我使用 math.cos()
检查了它。
当我尝试小数字时它工作得很好:
print("Result: ", cosine(25, 1000))
print(math.cos(25))
输出:
Result: 0.991203540954667
0.9912028118634736
数量还是差不多。但是当我尝试更大的数字时,即 40,它只是 returns 一个完全不同的值。
Result: 1.2101433786727471
-0.6669380616522619
有人知道为什么会这样吗?
离展开点越远,泰勒展开的误差项就越大(在本例中,x_0 = 0
)。为了减少错误,通过仅在区间 [0, 2 * pi]
:
def cosine(x, n):
x = x % (2 * pi)
total = 0
for i in range(0, n + 1):
total += ((-1) ** i) * (x**(2*i) / math.factorial(2*i))
return total
这可以进一步改进为[0, pi/2]
:
def cosine(x, n):
x = x % (2 * pi)
if x > pi:
x = abs(x - 2 * pi)
if x > pi / 2:
return -cosine(pi - x, n)
total = 0
for i in range(0, n + 1):
total += ((-1) ** i) * (x**(2*i) / math.factorial(2*i))
return total
与您得到的答案相反,无论参数有多大,这个泰勒级数都会收敛。项的分母中的阶乘最终使项变为 0。
但是在阶乘部分占主导地位之前,项的绝对值会越来越大。本机浮点数没有足够的精度位来保留足够的信息以供 low-order 位生存。
这是一种不会丢失任何精度的方法。它不实用,因为它很慢。相信我,我告诉你通常需要多年的经验才能学习如何编写实用、快速、high-quality 的数学库。
def mycos(x, nbits=100):
from fractions import Fraction
x2 = - Fraction(x) ** 2
i = 0
ntries = 0
total = term = Fraction(1)
while True:
ntries += 1
term = term * x2 / ((i+1) * (i+2))
i += 2
total += term
if (total // term).bit_length() > nbits:
break
print("converged to >=", nbits, "bits in", ntries, "steps")
return total
然后是你的例子:
>>> mycos(25)
converged to >= 100 bits in 60 steps
Fraction(177990265631575526901628601372315751766446600474817729598222950654891626294219622069090604398951917221057277891721367319419730580721270980180746700236766890453804854224688235663001, 179569976498504495450560473003158183053487302118823494306831203428122565348395374375382001784940465248260677204774780370309486592538808596156541689164857386103160689754560975077376)
>>> float(_)
0.9912028118634736
>>> mycos(40)
converged to >= 100 bits in 82 steps
Fraction(-41233919211296161511135381283308676089648279169136751860454289528820133116589076773613997242520904406094665861260732939711116309156993591792484104028113938044669594105655847220120785239949370429999292710446188633097549, 61825710035417531603549955214086485841025011572115538227516711699374454340823156388422475359453342009385198763106309156353690402915353642606997057282914587362557451641312842461463803518046090463931513882368034080863251)
>>> float(_)
-0.6669380616522619
注意事项:
full-precision 结果需要很多位。
四舍五入为浮点数,它们与您从
得到的完全一致math.cos()
.不需要接近 1000 步就可以收敛。