【发布时间】:2020-10-29 02:54:12
【问题描述】:
我最近需要快速找到10的反正弦值。我决定用python帮我计算一下:
cmath.asin(10)
根据经验,我预计第四象限会出现结果(正实数 (pi/2) 和负虚数)。惊喜……它返回了第一象限的结果。我也尝试过 numpy.arcsin ......结果相同。虽然返回值的正弦值确实是 10,但我不认为这是反正弦函数的标准主值。
>>> import math
>>> import numpy as np
>>> z=cmath.asin(10)
>>> z
(1.5707963267948966+2.993222846126381j)
>>> cmath.sin(z)
(9.999999999999998+6.092540900222251e-16j)
>>> z2=np.arcsin(10+0j)
>>> np.sin(z2)
(10+6.092540900222253e-16j)
我使用 numpy 发现了同样的结果(如上所示)。
是否有一个 python 模块,我可以期望从中获取复杂值函数的标准主值(即遵循主分支切割)?或者,标准主值的概念是否过于流畅在这一点上期待一致性?
-
通过 Wikipedia 页面 (https://en.wikipedia.org/wiki/Inverse_trigonometric_functions) 部分关于复数值的讨论,可以得出第四象限解决方案。
-
PSU 数学家发表的一篇关于复数反三角函数的文章 (http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.413.5729&rep=rep1&type=pdf) 也是如此。
【问题讨论】:
-
np.arcsin解释了它如何处理复杂的输入。由于我对复杂的数学有点生疏,你能把它的branch cuts翻译成你的象限吗? -
sympy给出1.5707963267949 - 2.99322284612638⋅ⅈ。我认为cmath和numpy函数依赖于底层c代码,而不是重新实现。 -
很公平。关键选择是关于如何处理带符号的零和分支切割:您是否忽略零的符号以决定您在分支切割的哪一侧,或者您是否根据零的符号进行区分?基于零符号的区分提供了一些不错的属性,例如
asin(conj(z))始终与conj(asin(z))相同,包括所有极端情况。但从数学上讲,这感觉有点像作弊。顺便说一句,我注意到 Python 和 NumPy 的文档在这里都具有误导性,使用“从下方连续”之类的措辞。 -
@hpaulj:不,
cmath不依赖于底层 C 代码。它确实重新实现了一些东西,但遵循 Kahan 的建议和 C 标准是一个深思熟虑的、有意识的选择。