为了账号安全,请及时绑定邮箱和手机立即绑定

Python - 计算 arcsin 时不准确

Python - 计算 arcsin 时不准确

吃鸡游戏 2023-03-01 16:32:48
我正在尝试在不使用任何外部库的情况下在 Python 中实现 arcsin。这是我的代码:from time import process_time as ptclass 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)        
查看完整描述

2 回答

?
翻翻过去那场雪

TA贡献2065条经验 获得超13个赞

的问题arcsin(1)是它arcsin(x)在 x=1 处垂直(导数无限增长)。像泰勒级数这样的多项式逼近跟不上。您的收敛速度非常慢,并且需要大量的项才能获得合适的近似值。你需要改变你处理问题的方式。

例如,对于小的 x,y = sin(pi/2 - x)近似为1 - x^2/2,您可以从中推导出近似值asin(y) = pi/2 - sqrt(2 - 2*y)。此近似值适用于非常接近 1 的值 - 您可以直接使用它。

如果你努力一点,你可以证明确切的身份

asin(x) = pi/2 - 2*asin( sqrt( (1-x)/2 ) )

使用此恒等式,您可以使用适用于接近 0 的asin(x)x 的现有函数来计算接近 1 的 x 。asin

例如:要计算,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)

这是在生产质量数学库实现中使用的技术 - 例如参见OpenLibmfdlibm


查看完整回答
反对 回复 2023-03-01
?
慕村225694

TA贡献1880条经验 获得超4个赞

一个非常基本的近似值将给出sum from 0 to N近似值(以弧度表示)。在这里,您以度为单位给出结果,因为度和弧度之间存在大致的比率,您需要将arcsin 设置为近似值。arcsin1e(-N)1e2NUM_ITER = 1e(N+2)1e(-N)

因此,对于您的具体问题,您需要使用N = 1(大约 1 分)进行测试,因此NUM_ITER = 1e(1+2) = 1,000. 这一点都不精确,但可以让您了解您正在寻找的价值。

然后,如果您想查找确切的值,我看不到每次都使用精确的数学方法(无论 x.point 精度如何)。但是,您可以使用二分法算法来查找NUM_ITER,如果它是您算法的目标。第一近似值将减少您的计算时间。

精确的近似值来自比率 orx^O(n)4^O(n),4^O(n)更大。我们可以用 来近似求和项O(1/10^n)

如果有人可以进行精确的微积分,我将非常高兴看到它。


查看完整回答
反对 回复 2023-03-01
  • 2 回答
  • 0 关注
  • 166 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信