numpy 中余弦的真正反函数?(不是 arccos)

Wol*_*ger 5 python trigonometry numpy

这是一个奇怪的:

我发现自己需要一个 numpy 函数,我称之为真正的反函数np.cos(或另一个三角函数,这里使用余弦来确定)。我所说的“真逆”是一个函数invcos,这样

np.cos(invcos(x)) = x
Run Code Online (Sandbox Code Playgroud)

对于任何实数浮点数 x。两个观察结果:invcos(x)存在(它是一个复杂的浮点)并且np.arccos(x)执行该工作,因为它仅适用于.-1 < x < 1

我的问题是是否有一个有效的 numpy 函数用于此操作,或者它是否可以轻松地从现有函数构建?

我的尝试是结合使用np.arccosnp.arccosh来手动构建该函数。这是基于这样的观察:如果 1 乘以复数单位,np.arccos则可以处理 [-1,1] 内的 x,并且可以处理 [-1,1] 之外的 x。np.arccosh要查看这是否有效:

cos_x = np.array([0.5, 1., 1.5])

x = np.arccos(cos_x)
cos_x_reconstucted = np.cos(x)
# [0.5 1.  nan]

x2 = 1j*np.arccosh(cos_x)
cos_x_reconstructed2 = np.cos(x2)
# [nan+nanj 1.-0.j 1.5-0.j]
Run Code Online (Sandbox Code Playgroud)

所以我们可以将其结合起来

def invcos(array):
    x1 = np.arccos(array)
    x2 = 1j*np.arccosh(array)
    print(x1)
    print(x2)
    x = np.empty_like(x1, dtype=np.complex128)
    x[~np.isnan(x1)] = x1[~np.isnan(x1)]
    x[~np.isnan(x2)] = x2[~np.isnan(x2)]
    return x

cos_x = np.array([0.5, 1., 1.5])
x = invcos(cos_x)
cos_x_reconstructed = np.cos(x)
# [0.5-0.j 1.-0.j 1.5-0.j]
Run Code Online (Sandbox Code Playgroud)

这给出了正确的结果,但自然会引发运行时警告:

RuntimeWarning: invalid value encountered in arccos.
Run Code Online (Sandbox Code Playgroud)

我想既然 numpy 甚至告诉我我的算法效率不高,那么它可能效率不高。有一个更好的方法吗?


对于对这个奇怪的函数为何有用感兴趣的读者:动机来自物理背景。在某些理论中,人们可以拥有“离壳”的向量分量,这意味着这些分量甚至可能比向量更长。尽管如此,上述函数对于根据角度参数化事物还是很有用的。

Kar*_*tel 4

我的问题是是否有一个有效的 numpy 函数用于此操作,或者它是否可以轻松地从现有函数构建?

是的; 这是... np.arccos

从文档中:

对于实值输入数据类型,arccos 始终返回实数输出。对于每个无法表示为实数或无穷大的值,它会生成 nan 并设置无效浮点错误标志。

对于复值输入,arccos 是一个复数解析函数,具有分支切割 [-inf, -1] 和 [1, inf],并且前者从上连续,后者从下连续。

所以我们需要做的就是确保输入是一个复数(即使它的虚部为零):

>>> import numpy as np
>>> np.arccos(2.0)
__main__:1: RuntimeWarning: invalid value encountered in arccos
nan
>>> np.arccos(2 + 0j)
-1.3169578969248166j
Run Code Online (Sandbox Code Playgroud)

对于数组,我们需要适当的dtype

>>> np.arccos(np.ones((3,3)) * 2)
array([[nan, nan, nan],
       [nan, nan, nan],
       [nan, nan, nan]])
>>> np.arccos(np.ones((3,3), dtype=np.complex) * 2)
array([[0.-1.3169579j, 0.-1.3169579j, 0.-1.3169579j],
       [0.-1.3169579j, 0.-1.3169579j, 0.-1.3169579j],
       [0.-1.3169579j, 0.-1.3169579j, 0.-1.3169579j]])
Run Code Online (Sandbox Code Playgroud)