2017-07-14 39 views
1

我试过但是当我键入这些翻译对Cordic wikipedia webpage斯威夫特CORDIC算法给定答案

的MATLAB语言:

print(cordic(beta: Double.pi/9, n: 20)) 
print(cordic(beta: Double.pi/8, n: 20)) 

我得到

[-0.17163433840184755, 0.98516072489744066] 
[-0.17163433840184755, 0.98516072489744066] 

它总是给我一个常数回答。为什么?我确定“角度”和“Kvalues”数组是正确计算的。

下面的代码:

import Foundation 

var angles: [Double] = [] 

for i: Double in stride(from: 0, to: 27, by: 1) { 
    angles.append(atan(pow(2, -i))) 
} 
var Kvalues: [Double] = [] 

for i: Double in stride(from: 0, to: 23, by: 1) { 
    Kvalues.append(1/sqrt(abs(Double(1) + pow(2,-2 * i)))) 
    if i > 0 { 
     Kvalues[Kvalues.count - 1] *= Kvalues[Kvalues.count - 2] 
    } 
} 
func min(_ a: Int, _ b: Int) -> Int { 
    return a > b ? b : a 
} 
func cordic(beta: Double, n: Int) -> [Double] { 
    var beta1 = beta 
    let Kn = Kvalues[min(n, Kvalues.count - 1)] 
    var v: [Double] = [1,0] 
    var poweroftwo: Double = 1 
    var angle = angles[0] 

    for j in 0 ..< n { 
     let sigma: Double = beta < 0 ? -1 : 1 
     let factor: Double = sigma * poweroftwo 
     v = [v[0] - v[1] * factor, v[1] + v[0] * factor] 
     beta1 -= sigma * angle 
     poweroftwo /= 2 
     angle = j + 2 > angles.count ? angle/2 : angles[j + 2] 
    } 
    return [v[0] * Kn, v[1] * Kn] 
} 
print(cordic(beta: Double.pi/9, n: 20)) 
print(cordic(beta: Double.pi/8, n: 20)) 

回答

1

你得到相同的结果不同的输入,因为在

let sigma: Double = beta < 0 ? -1 : 1 

beta应该是beta1,这是局部变量是 在循环更新。

但即使在修复后的结果不正确,并且这是由两个“off-by-one”索引错误引起的 。 algorithm description中的数组基于1,Swift数组基于0。所以

let Kn = Kvalues[min(n, Kvalues.count - 1)] 
// should be 
let Kn = Kvalues[min(n-1, Kvalues.count - 1)] 

angle = j + 2 > angles.count ? angle/2 : angles[j + 2] 
// should be 
angle = j + 1 >= angles.count ? angle/2 : angles[j + 1] 

anglesKvalues阵列应i从0被定义多达并包括 27 RESP。 23.

最后,没有必要定义自己的min函数,因为在Swift标准库中有一个函数。

全部放在一起你的代码是:

var angles: [Double] = [] 

for i: Double in stride(from: 0, through: 27, by: 1) { 
    angles.append(atan(pow(2, -i))) 
} 
var Kvalues: [Double] = [] 

for i: Double in stride(from: 0, through: 23, by: 1) { 
    Kvalues.append(1/sqrt(abs(Double(1) + pow(2,-2 * i)))) 
    if i > 0 { 
     Kvalues[Kvalues.count - 1] *= Kvalues[Kvalues.count - 2] 
    } 
} 

func cordic(beta: Double, n: Int) -> [Double] { 
    var beta1 = beta 
    let Kn = Kvalues[min(n-1, Kvalues.count - 1)] 
    var v: [Double] = [1,0] 
    var poweroftwo: Double = 1 
    var angle = angles[0] 

    for j in 0 ..< n { 
     let sigma: Double = beta1 < 0 ? -1 : 1 
     let factor: Double = sigma * poweroftwo 
     v = [v[0] - v[1] * factor, v[1] + v[0] * factor] 
     beta1 -= sigma * angle 
     poweroftwo /= 2 
     angle = j + 1 >= angles.count ? angle/2 : angles[j + 1] 
    } 
    return [v[0] * Kn, v[1] * Kn] 
} 

和产生良好的近似值:

print(cordic(beta: Double.pi/9, n: 20)) // [0.93969210812600046, 0.34202155184390554] 
print(cordic(beta: Double.pi/8, n: 20)) // [0.92388022188807306, 0.38268176805806309] 

的精确值是

print(cos(Double.pi/9), sin(Double.pi/9)) // 0.939692620785908 0.342020143325669 
print(cos(Double.pi/8), sin(Double.pi/8)) // 0.923879532511287 0.38268343236509