numpy角度函数对于相同的输入返回不同的答案?

问题描述

我正在使用Python 3.7.7和numpy 1.19.1。这是代码

import numpy as np
a = 55.74947517067784019673 + 0j
print(f'{-a == -1 * a},{np.angle(-a)},{np.angle(-1 * a)}')

这是输出

True,-3.141592653589793,3.141592653589793

我有两个问题:

  1. 为什么角度函数为同一输入提供不同的输出
  2. 根据文档,角度输出范围为(-pi,pi],为什么输出之一为-np.pi

解决方法

如果您查看np.angle中的the source,它将使用功能np.arctan2。现在,根据numpy docsnp.arctan2使用基础C库,该库具有以下规则:

请注意,+ 0和-0是不同的浮点数,+ inf和-inf也是如此。

,使用+/-0进行计算时会导致不同的行为。因此,在这种情况下,规则是:

y: +/- 0
x: <0
angle: +/- pi

现在,如果您尝试:

a = 55.74947517067784019673
print(f'{-a == -1 * a},{np.angle(-a)},{np.angle(-1 * a)}')
#True,3.141592653589793,3.141592653589793

,如果您尝试:

a = 55.74947517067784019673 + 0j
print(-a)
#(-55.74947517067784-0j)
print(-1*a)
#(-55.74947517067784+0j)
print(f'{-a == -1 * a},-3.141592653589793,3.141592653589793

符合图书馆协议。

关于您的第二个问题,我想这是错字/错误,因为np.arctan2 doc说:

以弧度表示的角度数组,范围为 [-pi,pi] 。如果x1和x2均为标量,则为标量。

-a-1*a的解释

首先,55.74947517067784019673 + 0j构造复数,而只是将浮点数添加到复数(以明确构造复数)请使用complex(55.74947517067784019673,0.0),并注意整数没有带符号的零,只有浮点数有)。 -a只是简单地恢复符号,并且很容易解释。让我们看看在计算-1*a时会发生什么:

为简单起见,假设a = 55.5 + 0j

  • 第一个a = 55.5+0j转换为complex(55.5,0.0)
  • 第二-1等于complex(-1.0,0.0)
  • 然后,complex(-1.0,0.0)*complex(55.5,0.0)等于complex((-1.0*55.5 - 0.0*0.0),(-1.0*0.0 + 0.0*55.5))等于complex((-55.5 - 0.0),(-0.0 + 0.0)),然后等于complex(-55.5,0.0)

请注意,-0.0+0.0等于0.0,并且符号规则仅适用于此link中提及并在以下注释中引用的乘法和除法。为了更好地理解它,请参见:

print(complex(-1.0,-0.0)*complex(55.5,0.0))
#(-55.5-0j)

虚部为(-0.0*55.5 - 1.0*0.0) = (-0.0 - 0.0) = -0.0

,

对于1)打印-a-1*a,您会发现它们是不同的。

-a
Out[4]: (-55.74947517067784-0j)

-1*a
Out[5]: (-55.74947517067784+0j) # note +0j not -0j

在不了解numpy实现的细节的情况下,虚部的符号可能用于计算角度...这可以解释为什么这种退化情况给出不同的结果。

对于2),这对我而言似乎是一个错误或doco错误...