Python-计算Arcin时不准确
我试图在Python中实现arcsin,而不使用任何外部库 这是我的密码:Python-计算Arcin时不准确,python,python-3.x,math,trigonometry,Python,Python 3.x,Math,Trigonometry,我试图在Python中实现arcsin,而不使用任何外部库 这是我的密码: from time import process_time as pt class TrigoCalc(metaclass=__readonly): # This class evaluates various Trigonometric functions # including Inverse Trigonometric functions def __setattr__(self, na
from time import process_time as pt
class TrigoCalc(metaclass=__readonly):
# This class evaluates various Trigonometric functions
# including Inverse Trigonometric functions
def __setattr__(self, name, value):
raise Exception("Value can't be changed")
@staticmethod
def asin(x):
'''Implementation from Taylor series
asin(x) => summation[(2k)! * x^(2k + 1) / (2^(2k) * (k!)^2 * (2k + 1))]
k = [0, inf)
x should be real
'''
# a0 = 1
# a1 = 1/(2*3)
# a2 = 1/2 * 3/(4*5)
# a3 = 1/2 * 3/4 * 5/(6*7)
# a4 = 1/2 * 3/4 * 5/6 * 7/(8*9)
# a5 = 1/2 * 3/4 * 5/6 * 7/8 * 9/(10*11)
# a6 = 1/2 * 3/4 * 5/6 * 7/8 * 9/10 * 11/(12*13)
# a7 = 1/2 * 3/4 * 5/6 * 7/8 * 9/10 * 11/12 * 13/(14*15)
# a8 = 1/2 * 3/4 * 5/6 * 7/8 * 9/10 * 11/12 * 13/14 * 15/(16*17)
# a9 = 1/2 * 3/4 * 5/6 * 7/8 * 9/10 * 11/12 * 13/14 * 15/16 * 17/(18*19)
# a10 = 1/2 * 3/4 * 5/6 * 7/8 * 9/10 * 11/12 * 13/14 * 15/16 * 17/18 * 19/(20*21)
# taking 10 coefficients for arriving at a common sequence
# N = n, D = n + 1; (N/D) --> Multiplication, number of times the coefficient number, n >= 1
start_time = pt()
coeff_list = []
NUM_ITER = 10000
for k in range(NUM_ITER):
if k == 0:
coeff_list.append(1)
else:
N = 1
D = N + 1
C = N/D
if k >= 2:
for i in range(k-1):
N += 2; D += 2
C = C * N/D
coeff_list.append(C)
__sum = 0
for k in range(NUM_ITER):
n = coeff_list[k] * math_utils.power(x, 2*k + 1) / (2*k + 1)
__sum += n
# Radian conversion to degrees
__sum = __sum/TrigoCalc.pi * 180
end_time = pt()
print(f'Execution time: {end_time - start_time} seconds')
return __sum
结果
当NUM_ITER
为60
(无限级数迭代60次)时,x=1
极点的计算存在显著的不精确性,而x=1/2
给出14点精度
In [2]: TrigoCalc.asin(0.5)
Execution time: 0.0 seconds
Out[2]: 30.000000000000007
In [3]: TrigoCalc.asin(1)
Execution time: 0.0 seconds
Out[3]: 85.823908877692
两次运行中的执行时间都不明显
当NUM_ITER
为10000
时,则在x=1
极,结果比上一次运行更精确,但在x=1/2
时,精度完全相同
In [4]: TrigoCalc.asin(0.5)
Execution time: 19.109375 seconds
Out[4]: 30.000000000000007
In [5]: TrigoCalc.asin(1)
Execution time: 19.109375 seconds
Out[5]: 89.67674183336727
对于这种类型的计算,这两次运行的执行时间非常长
问题
如何平衡代码,以便在较小的NUM_ITER
中,在x=1
极点处至少提供1点精度
请随时提供建议或更新的代码
Python版本:3.7.7
编辑:在@Joni的答案的帮助下更改代码以获得精确的结果
asin()中的另一个函数中
:
asin()中的新函数将限制添加到x
,以避免收敛缓慢:
if -1.0 <= x < -0.5:
return -(TrigoCalc.pi/2 - __arcsin_calc(math_utils.power((1 - x*x), 0.5))) / TrigoCalc.pi * 180 # Radian to Degree conversion
elif -0.5 <= x <= 0.5:
return __arcsin_calc(x)/TrigoCalc.pi * 180
elif 0.5 < x <= 1.0:
return (TrigoCalc.pi/2 - __arcsin_calc(math_utils.power((1 - x*x), 0.5))) / TrigoCalc.pi * 180
else:
raise ValueError("x should be in range of [-1, 1]")
非常基本的近似值将给出
从0到N的和近似弧心在1e(-N)
(以弧度表示)。
这里,您给出的是以度为单位的结果,因为度和弧度之间大致存在1e2
,因此需要设置NUM\u ITER=1e(N+2)
来近似1e(-N)
因此,对于您的特定问题,您需要使用N=1
(约1分)进行测试,因此NUM_ITER=1e(1+2)=1000
。这一点都不精确,但给出了您所寻找的价值的概念
那么,如果你想寻找精确的值,我没有看到每次都使用精确的数学方法(无论x点的精度如何)。
但是,如果是算法的目标,则可以使用二分法算法来查找NUM\u ITER
。第一个近似值将减少计算时间
精确的近似值来自比率orx^O(n)
和4^O(n)
,4^O(n)
更大。我们可以用O(1/10^n)
来近似求和项
如果有人能做一个精确的微积分,我会非常高兴看到它。一个非常基本的近似值将给出从0到N的和近似值在1e(-N)
(以弧度表示)。
这里,您给出的是以度为单位的结果,因为度和弧度之间大致存在1e2
,因此需要设置NUM\u ITER=1e(N+2)
来近似1e(-N)
因此,对于您的特定问题,您需要使用N=1
(约1分)进行测试,因此NUM_ITER=1e(1+2)=1000
。这一点都不精确,但给出了您所寻找的价值的概念
那么,如果你想寻找精确的值,我没有看到每次都使用精确的数学方法(无论x点的精度如何)。
但是,如果是算法的目标,则可以使用二分法算法来查找NUM\u ITER
。第一个近似值将减少计算时间
精确的近似值来自比率orx^O(n)
和4^O(n)
,4^O(n)
更大。我们可以用O(1/10^n)
来近似求和项
如果有人能做精确的微积分,我会非常高兴看到。Arcin(1)
的问题是,Arcin(x)
在x=1时垂直(导数无边界增长)。像泰勒级数这样的多项式近似法跟不上它。收敛速度很慢,需要大量的项才能得到合适的近似值。你需要改变处理问题的方式
例如,对于小x,y=sin(pi/2-x)
大约是1-x^2/2
,从中可以导出近似值asin(y)=pi/2-sqrt(2-2*y)
。此近似值适用于非常接近1的值-您可以直接使用它
如果你再努力一点,你就能证明确切的身份
使用此标识,您可以使用对0附近的x有利的现有asin
函数,为1附近的x计算asin(x)
例如:要计算asin(0.99)
,您需要计算:
asin(0.99) = pi/2 - 2*asin( sqrt( (1-.99)/2 ) )
= pi/2 - 2*asin( sqrt(.005) )
= pi/2 - 2*asin(0.07071067811865475)
。。。然后,您将使用现有算法获得asin(0.07071067811865475)
的高质量近似值
这是生产质量数学库实现中使用的技术-例如,请参见或。Arcin(1)
的问题是,Arcin(x)
在x=1时垂直(导数无边界增长)。像泰勒级数这样的多项式近似法跟不上它。收敛速度很慢,需要大量的项才能得到合适的近似值。你需要改变处理问题的方式
例如,对于小x,y=sin(pi/2-x)
大约是1-x^2/2
,从中可以导出近似值asin(y)=pi/2-sqrt(2-2*y)
。此近似值适用于非常接近1的值-您可以直接使用它
如果你再努力一点,你就能证明确切的身份
使用此标识,您可以使用对0附近的x有利的现有asin
函数,为1附近的x计算asin(x)
例如:要计算asin(0.99)
,您需要计算:
asin(0.99) = pi/2 - 2*asin( sqrt( (1-.99)/2 ) )
= pi/2 - 2*asin( sqrt(.005) )
= pi/2 - 2*asin(0.07071067811865475)
。。。然后,您将使用现有算法获得asin(0.07071067811865475)
的高质量近似值
这是第
asin(x) = pi/2 - 2*asin( sqrt( (1-x)/2 ) )
asin(0.99) = pi/2 - 2*asin( sqrt( (1-.99)/2 ) )
= pi/2 - 2*asin( sqrt(.005) )
= pi/2 - 2*asin(0.07071067811865475)