问题
So, I'm trying to write an algorithm croot(k, n), that returns the kth root of unity with n == n. I'm getting mostly the right answer, however it's giving me really weird representations that seem wrong for certain numbers. Here is an example.
import cmath
def croot(k, n):
if n<=0:
return None
return cmath.exp((2 * cmath.pi * 1j * k) / n)
for k in range(8):
print croot(k, 8)
Output is:
(1+0j)
(0.70710...+0.70710...j)
(6.12323399574e-17+1j)
Whoa whoa whoa. So the root when k = 2 and n = 8 is wrong, as it should just be i, which would be represented like 1j, or j, or 1.00000j, etc. Could somebody help me here? I'm doing this because I'm trying to write an FFT algorithm. I'm not very experienced with complex numbers and Python so I could very well be making a simple mistake.
Thanks,
If you guys need any additional information just ask.
回答1:
Look at this number
(6.12303176911e-17+1j)
6.12303176911e-17
= 0.0000000000000000612303176911
which is really small (close to zero). What you are seeing is rounding errors due to the limited representation of floating point numbers
The error is equivalent to measuring the distance to the sun to within 10 microns or so. If you're running FFTs on data from the real world the measurement errors are usually far larger than this.
回答2:
Here's cube roots of unity and 4th roots for a usage example. The input array should be interpreted as polynomial coefficients.
>>> import numpy as np
>>> np.roots([1, 0, 0, -1])
array([-0.5+0.8660254j, -0.5-0.8660254j, 1.0+0.j ])
>>> np.roots([1, 0, 0, 0, -1])
array([ -1.00000000e+00+0.j, 5.55111512e-17+1.j, 5.55111512e-17-1.j,
1.00000000e+00+0.j])
edit: The polynomial coefficients are given in the input array p
to np.roots(p)
in the following order:
p[0] * x**n + p[1] * x**(n-1) + ... + p[n-1]*x + p[n]
So, for example, to return the n
th roots of unity, which are the solutions of the equation 1 * x**n - 1 == 0
, you would use an input like p = [1] + [0] * (n - 1) + [-1]
.
回答3:
Using Python 3.5.2, numpy.roots
ran out of memory and crashed my Chromebook when I tried to determine the 1,200th roots of unity. The crash occurred when they construct the companion matrix to the polynomial, so I don't think they're using a sparse representation. From the docs:
The algorithm relies on computing the eigenvalues of the companion matrix
If you just need to compute the roots of unity, a trigonometric approach is asymptotically better in both time and space complexity:
def nthRootsOfUnity1(n): # linear space, parallelizable
from numpy import arange, pi, exp
return exp(2j * pi / n * arange(n))
If you're willing to give up on parallelization, you can use generators to achieve constant space and constant time for each additional root, whereas the first method must compute all n roots before returning:
def nthRootsOfUnity2(n): # constant space, serial
from cmath import exp, pi
c = 2j * pi / n
return (exp(k * c) for k in range(n))
On my machine and without using parallelization, these methods compute the 10,000,000th roots in the time it takes numpy.roots
to compute the 1,000th roots:
In [3]: n = 1000
In [4]: %time _ = sum(numpy.roots([1] + [0]*(n - 1) + [-1]))
CPU times: user 40.7 s, sys: 811 ms, total: 41.5 s
Wall time: 10.8 s
In [5]: n = 10000000
In [6]: %time _ = sum(nthRootsOfUnity1(n))
CPU times: user 4.98 s, sys: 256 ms, total: 5.23 s
Wall time: 5.23 s
In [7]: %time _ = sum(nthRootsOfUnity2(n))
CPU times: user 11.6 s, sys: 2 ms, total: 11.6 s
Wall time: 11.6 s
来源:https://stackoverflow.com/questions/15424449/calculating-nth-roots-of-unity-in-python