对于2的幂,准确的统一根源?

时间:2014-01-06 16:02:54

标签: algorithm complex-numbers

统一的第n个根是多项式方程x^n = 1的解。 n = 2^k是否有一个众所周知的算法,对于某些k(即n为2的幂)?

有许多算法用于计算单位的第n个根。例如,这是一个使用Numpy的“根”函数返回根数组的Python实现。

import numpy as np;
def omegas(n):
    #make the n-degree polynomial and solve for its roots
    poly = [0]*(n+1)
    poly[0] = -1; #constant
    poly[-1] = 1; #highest degree
    return np.roots(poly)

您也可以使用触发功能:

import numpy as np
import cmath
def trig_omegas(n):
    return np.array([cmath.rect(1,x*np.pi) for x in range(n)])

但准确性让我想要。这就是答案应该是,对于n = 4:

array([-1.+0.j,  0.+1.j, -0.-1.j,  1.+0.j])
#or, in counterclockwise order
array([ 1.+0.j,  0.+1.j, -1.+0.j, -0.-1.j])

这是上述功能的结果。

>>> omegas(4)
array([ -1.00000000e+00+0.j,   8.32667268e-17+1.j,   8.32667268e-17-1.j,
         1.00000000e+00+0.j])
>>> trig_omegas(4)
array([ 1. +0.00000000e+00j, -1. +1.22464680e-16j,  1. -2.44929360e-16j,
       -1. +3.67394040e-16j])

尾随零表示最后有一个小错误。 omegas(4)的第一个条目实际上比-1小一点。

  
    
      

OMEGAS(4)[0]           (-1.0000000000000004 + 0j的)

    
  

有没有更好的方法来获得2的权力统一的根源?

3 个答案:

答案 0 :(得分:1)

这是一个递归算法,它通过取n / 2个根和两者之间的点来生成n个根。如果n为4或更低,则硬编码结果(因为在复平面上你永远不会找到-1和1的两个中点)。否则,它找到n / 2个根,每两个连续的根,在它们的角平分线上找到一个点,并将其指向单位圆。

import numpy as np
#power of 2 roots of unity
#computed by recursively taking the averages of the n/2 roots
def omegas_2(n):
    #base cases
    if n == 1:
        return np.array([1])
    if n == 2:
        return np.array([1,-1])
    if n == 4: # need three points to specify the plane
        return np.array([1,1j,-1,-1j])

    halfroots = omegas_2(n//2)
    result = np.empty(n)
    for i in range(n//2):
        result[2*i] = halfroots[i];

        #take the center of the i'th and the i+1'th n/2-root
        result[2*i+1] = (halfroots[i]+halfroots[(i+1)%(n//2)]);
        result[2*i+1] /= abs(result[2*i+1]); #normalize to length 1
    return result

答案 1 :(得分:1)

您可能喜欢图书馆Sympy。尝试解决统一的第五根

solve(x**5-1)
http://live.sympy.org/

的控制台中

要将精确解转换为浮点近似,请执行[x.evalf() for x in solve(x**5-1)]

答案 2 :(得分:0)

Maxima实施:

omegan(n):=block( [ hr, hn, q, j ],
    local(ret),
    if n=1 then return([1]),
    if n=2 then return([1, -1]),
    if n=4 then return([1, %i, -1, -%i]),
    if oddp(n) then error ("length must be power of 2; found ", n),
    hn:fix(n/2),
    hr: omegan(hn),
    for i:1 thru hn do (
        ret[2*i]:hr[i],
        j: if i+1>hn then i+1-hn else i+1,
        q:hr[i]+hr[j],          
        ret[2*i+1]:rectform(q/abs(q))
    ),  
    listarray (ret)     
)