所以我创建了一个使用泰勒系列近似arctan(x)的函数。如下所示:
def arctan(x,n):
arctang=0
for i in range(n):
sign=(-1)**i
arctang = arctang + ((x**(2.0*i+1))/(2.0*i+1))*sign
return arctang
print("arctan(x)=", arctan(x,n))
用户输入介于-1和1之间的x值,以及输入n的整数。但我希望能够扩展函数,以便用户可以输入x的任何值,通过语句
如果x> 0,则arctan(x)=(pi / 2)-arctan(1 / x)
如果x <0,arctan(x)= - (pi / 2)-arctang(1 / x)
所以我将功能更改为以下内容:
import math
def arctan(x, n):
arctang=0
inv_x=1/x
for i in range(n):
sign=(-1)**i
arctang = arctang + ((inv_x**(2.0*i+1))/(2.0*i+1))*sign
if x>0:
arc_tan=(math.pi/2)-arctang
else:
arc_tan=-(math.pi/2)-arctang
return arc_tan
print("arctan(x)=", arctan(x,n))
但是当我为x和n选择任意值时,例如:x = 1且n = 20,该函数返回的值不正确。我在使用的方程式中没有看到任何错误。
如果有人能发现什么是错的,将不胜感激!
答案 0 :(得分:0)
这是针对arctangent的Taylor系列的Python 2 / Python 3实现,它使用我在评论中提到的优化。它还处理abs(x) > 1
。该系列确实收敛-1 <= x <= 1
(尽管当我们接近该范围的端点时,收敛非常慢),但如果我们只使x
为正,则更简单。
要使用浮动幂(使用**
运算符或pow
函数)执行取幂,Python使用对数,这比简单乘法慢,并且它通常比乘法。当然,我们可以通过将x**(2.0*i+1)
更改为x**(2*i+1)
来消除浮动能力,但最好在可行的情况下避免取幂。
我们可以在这里做到这一点,因为该系列中每个词的x
的力量比前一个词的2倍。因此,我们可以在循环外计算x²
,并将其用作循环中的乘数,以计算前一个x
所需的每个幂。
此外,这里绝对不需要使用(-1)**i
来计算符号。符号在每个术语上交替出现,因此我们可以在循环外初始化sign
,然后在每次循环迭代时将其否定。
我的测试代码使用的x
值会很快收敛。它调用数学模块中的atan
函数来检查我们的近似值与正确值的接近程度。
from __future__ import print_function, division
from math import pi, atan
def arctan(x, terms):
argsign = -1 if x < 0 else 1
x *= argsign
if x > 1:
x = 1 / x
inverted = True
else:
inverted = False
result = term = x
x2 = x * x
sign = -1
for i in range(3, 2 * terms, 2):
term *= x2
result += sign * term / i
sign = -sign
if inverted:
result = pi / 2 - result
return argsign * result
# Tests
m = 0.1
terms = 10
print(' x: arctan(x) diff')
fmt = '{0:9.5f}: {1:11.8f} {2:14.8g}'
for i in range(1, 10):
x = m * i
y = arctan(x, terms)
print(fmt.format(x, y, y - atan(x)))
print()
for i in range(1, 10):
x = -m * i
y = arctan(x, terms)
print(fmt.format(x, y, y - atan(x)))
print()
for i in range(1, 10):
x = 1 / (m * i)
y = arctan(x, terms)
print(fmt.format(x, y, y - atan(x)))
print()
for i in range(1, 10):
x = -1 / (m * i)
y = arctan(x, terms)
print(fmt.format(x, y, y - atan(x)))
print()
<强>输出强>
x: arctan(x) diff
0.10000: 0.09966865 -2.7755576e-17
0.20000: 0.19739556 -8.3266727e-17
0.30000: 0.29145679 -4.6035398e-13
0.40000: 0.38050638 -1.8275848e-10
0.50000: 0.46364759 -1.8491727e-08
0.60000: 0.54041871 -7.8657695e-07
0.70000: 0.61070757 -1.8390105e-05
0.80000: 0.67446342 -0.00027752053
0.90000: 0.72981546 -0.0029996458
-0.10000: -0.09966865 2.7755576e-17
-0.20000: -0.19739556 8.3266727e-17
-0.30000: -0.29145679 4.6035398e-13
-0.40000: -0.38050638 1.8275848e-10
-0.50000: -0.46364759 1.8491727e-08
-0.60000: -0.54041871 7.8657695e-07
-0.70000: -0.61070757 1.8390105e-05
-0.80000: -0.67446342 0.00027752053
-0.90000: -0.72981546 0.0029996458
10.00000: 1.47112767 -2.220446e-16
5.00000: 1.37340077 0
3.33333: 1.27933953 4.6029847e-13
2.50000: 1.19028995 1.8275848e-10
2.00000: 1.10714874 1.8491727e-08
1.66667: 1.03037761 7.8657695e-07
1.42857: 0.96008875 1.8390105e-05
1.25000: 0.89633291 0.00027752053
1.11111: 0.84098087 0.0029996458
-10.00000: -1.47112767 2.220446e-16
-5.00000: -1.37340077 0
-3.33333: -1.27933953 -4.6029847e-13
-2.50000: -1.19028995 -1.8275848e-10
-2.00000: -1.10714874 -1.8491727e-08
-1.66667: -1.03037761 -7.8657695e-07
-1.42857: -0.96008875 -1.8390105e-05
-1.25000: -0.89633291 -0.00027752053
-1.11111: -0.84098087 -0.0029996458
请注意,编写良好的数学库中的反正切函数不使用简单的泰勒级数。有更复杂的算法,对于接近±1的值收敛速度更快,并且不易出现浮点运算的舍入误差。