'Why does numpy.angle(0+0j) answer pi instead of zero
I am creating an array of complex numbers and compute the angle.
When I set the magnitude to zero, I expect the angle to always be zero. However, I get pi if the phase is in the range of pi/2 to pi.
Here is my example code:
import numpy as np
import matplotlib.pyplot as plt
def main():
# s = np.full(360, 1) # Use this instead of np.zeros to get expected results
s = np.zeros(360)
f = 1 / s.size
t = np.arange(s.size)
s = s * np.exp(1j * 2*np.pi * f * t)
fig, axs = plt.subplots(2, 2)
axs[0,0].set_title("Magnitude")
axs[0,0].grid()
axs[0,0].plot(t, abs(s))
axs[1,0].set_title("Phase")
axs[1,0].grid()
axs[1,0].plot(t, np.angle(s))
# axs[1,0].plot(t, np.arctan2(np.imag(s), np.real(s)))
axs[0,1].set_title("Real")
axs[0,1].grid()
axs[0,1].plot(t, np.real(s))
axs[1,1].set_title("Imag")
axs[1,1].grid()
axs[1,1].plot(t, np.imag(s))
plt.show()
if __name__ == "__main__":
main()
Here is the output of the test program
I have also tried arctan2 and get the same behaviour.
Solution 1:[1]
Why does numpy.angle(0+0j) answer pi instead of zero
I did check numpy.angle docs, they claim
Although the angle of the complex number 0 is undefined, numpy.angle(0) returns the value 0.
so I did checked that
import numpy as np
assert np.angle(0+0j) == 0
and it does work as described in docs, I have used NumPy version 1.18.1, please check your version of NumPy. Maybe you are using one such ancient that described extension to numpy.angle was not implemented?
Solution 2:[2]
As @harold points out, not all elements are the same:
In [154]: s = np.zeros(360)
...: f = 1 / s.size
...: t = np.arange(s.size)
...: s = s * np.exp(1j * 2*np.pi * f * t)
...:
In [155]: s
Out[155]:
array([ 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
...
-0.+0.j, -0.+0.j, -0.+0.j, -0.+0.j, -0.+0.j, -0.+0.j, -0.+0.j,
-0.+0.j, -0.+0.j, -0.+0.j, -0.+0.j, -0.+0.j, -0.+0.j, -0.+0.j,
...])
In [156]: np.angle(s)
Out[156]:
array([ 0. , 0. , 0. , 0. , 0. ,
0. , 0. , 0. , 0. , 0. ,
0. , 0. , 0. , 0. , 0. ,
...
0. , 3.14159265, 3.14159265, 3.14159265, 3.14159265,
3.14159265, 3.14159265, 3.14159265, 3.14159265, 3.14159265,
3.14159265, 3.14159265, 3.14159265, 3.14159265, 3.14159265,
...])
You had a question about the results of np.angle, so the logical debugging step is to examine the argument to that function. Next step is to figure out why some elements are -0.0+0.0j.
Solution 3:[3]
Answering to my own question:
The root cause seems to be the behaviour of math.atan2, as in the following code:
print(math.atan2(0.0, 0.0))
print(math.atan2(0.0, -0.0))
print(math.atan2(-0.0, 0.0))
print(math.atan2(-0.0, -0.0))
which prints on my system:
0.0
3.141592653589793
-0.0
-3.141592653589793
It is the same results as if the real part was non-zero, so that seems to be the rationale:
print(math.atan2(0.0, 1))
print(math.atan2(0.0, -1))
print(math.atan2(-0.0, 1))
print(math.atan2(-0.0, -1))
So coming back to numpy, the documentation of numpy.angle says that:
Although the angle of the complex number 0 is undefined, numpy.angle(0) returns the value 0.
This seems to be incorrect if the real part of the complex number is -0.0.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Daweo |
| Solution 2 | hpaulj |
| Solution 3 | edw |
