代码之家  ›  专栏  ›  技术社区  ›  Quiche31

符号反三角函数并不总是返回期望的分数

  •  0
  • Quiche31  · 技术社区  · 3 年前

    假设cos(pi/3)是1/2,tan(pi/4)是1,我预计acos(1/2)返回pi/3,atan(1/1)返回pi/4。但SymPy分别返回1.04719755119660和0.785398163397448。但是,通过使用sqrt()作为解决方法,可以返回正确的pi/3和pi/4值。为什么?

    import sympy as sp
    
    print(sp.acos(1/2))
    # 1.04719755119660
    print(sp.acos(sp.sqrt(1)/2))
    # pi/3
    
    print(sp.atan(1/1))
    # 0.785398163397448
    print(sp.atan(sp.sqrt(1)/1))
    # pi/4
    
    2 回复  |  直到 3 年前
        1
  •  1
  •   nail steiger    3 年前

    好吧,所以我认为你遇到了这个问题,因为SymPy没有立即将你给它的输入识别为特殊值。当你给它输入1/2或1/1时,它只会想“啊,一个十进制数字,让我给你一个十进制的答案。”它甚至不会检查你给它的十进制是否代表π的整数或类似的东西。

    另一方面,当你使用sqrt()时,它就像一个标志,让SymPy说“嘿,这不仅仅是一个旧数字,它是一个特殊的数字!”因为sqrt(1)在数学上比1更“复杂”,所以SymPy停下来想“等一下,我最好在输出十进制答案之前检查一下这是否是一个特别的值。”,它会检查这些值是否是特殊值(它们是,对应于pi/3和pi/4),因此它会根据pi给出答案。

    这有点像我问你“2的一半是什么?”你说“1”,但如果我问你”4的平方根的一半是多少?“你可能会想”等等,4的平方根就是2,哦,2的一半就是1!“这是同一个答案,但我问这个问题的方式让你对它的看法有点不同。

        2
  •  0
  •   Quiche31    3 年前

    https://stackoverflow.com/users/22159264/nail-steiger 是正确的,我用以下内容验证了他的说法:

    import sympy as sp
    import numpy as np
    
    print(type(1/1))
    # float
    print(type(np.sqrt(1)/1))
    # numpy.float64
    print(type(sp.sqrt(1)/1))
    # sympy.core.numbers.One
    

    我提出这个问题的动机是得到一个简单的函数,将复数从笛卡尔形式转换为极坐标形式(也许这已经存在于某个库中)。因此,诀窍是始终使用sympy.sqrt(1)来强制atan的参数为sympy.core.numbers.*类型,而不是float或numpy.float64。以下是工作代码:

    import sympy as sp
    
    def to_polar(z):
        r = sp.sqrt(sp.re(z)**2 + sp.im(z)*2)
        theta = sp.atan(sp.sqrt(1)*sp.im(z)/sp.re(z))
        return (r, theta)
    
    # polar form for -3+3i
    print(to_polar(-3+3*I))
    # (3*sqrt(2), -pi/4)
    
    # polar form for 4+i
    print(to_polar(4+I))
    # (sqrt(17), atan(1/4))
    
    # polar form for -2+pi*i
    print(to_polar(-2+pi*I))
    # (sqrt(4 + pi**2), -atan(pi/2))