2017-07-14 1 views
1

ich die MATLAB-Sprache auf Cordic wikipedia webpageSwift CORDIC-Algorithmus gibt konstante Antwort

jedoch zu übersetzen versucht, wenn ich schreibe jene:

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

ich

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

Es gibt mir immer eine konstante Antworten. Warum? Ich bin mir sicher, dass die Arrays "angle" und "Kvalues" richtig berechnet werden.

Hier ist der Code:

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)) 

Antwort

1

Sie das gleiche Ergebnis für unterschiedlichen Eingang erhalten, weil in

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

betabeta1 sein soll, die die lokale Variable ist, die in der Schleife aktualisiert ist.

Aber auch nach der Fixierung, dass die Ergebnisse nicht korrekt sind, und das ist verursacht durch zwei "off-by-one" Indexfehler. Die Arrays in der sind 1-basiert und Swift-Arrays sind 0-basiert. So

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

und

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

Die angles und Kvalues Arrays sollten für i von 0 bis und einschließlich 27 bzw. definiert werden. 23.

Schließlich müssen Sie keine eigene min-Funktion definieren, da diese in der Swift-Standardbibliothek vorhanden ist.

sie alle zusammen Ihren Code Putting wäre:

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] 
} 

Und das bringt gute Annäherungen:

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

Die genauen Werte sind

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