Swift CORDIC算法给出了不变的答案

时间:2017-07-14 19:27:02

标签: swift trigonometry

我试图在Cordic wikipedia webpage

上翻译MATLAB语言

然而,当我输入那些:

Sub ListFilesInFolders()

Range("A:C").ClearContents
Range("A1").Value = "Folder Name"
Range("B1").Value = "File Name"
Range("C1").Value = "File Short Path"
Range("D1").Value = "File Type"
Range("A1").Select

Dim strPath As String
Dim sht As Worksheet
Dim LastRow As Long



'strPath = "C:\Data Collection\"
strPath = GetFolder

Dim OBJ As Object, Folder As Object, File As Object

Set OBJ = CreateObject("Scripting.FileSystemObject")
Set Folder = OBJ.GetFolder(strPath)

Call ListFiles(Folder)

Dim SubFolder As Object

For Each SubFolder In Folder.SubFolders
    Call ListFiles(SubFolder)
    Call GetSubFolders(SubFolder)
Next SubFolder

MsgBox ("DONE!!!")
End Sub

''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

Sub ListFiles(ByRef Folder As Object)

If Folder Like "*History*" Then
    Exit Sub
End If

Set sht = ThisWorkbook.Worksheets("Sheet1")

'Ctrl + Shift + End
r = sht.Cells(sht.Rows.Count, "A").End(xlUp).Row + 1

With ActiveSheet

On Error Resume Next
For Each File In Folder.Files

        .Cells(r, 1).Value = File.ParentFolder
        .Cells(r, 2).Value = File.ShortName
        .Cells(r, 3).Value = File.ShortPath
        .Cells(r, 4).Value = File.Type

r = r + 1
Next File

End With

End Sub

''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

Sub GetSubFolders(ByRef SubFolder As Object)

Dim FolderItem As Object
On Error Resume Next
For Each FolderItem In SubFolder.SubFolders
    Call ListFiles(FolderItem)
    Call GetSubFolders(FolderItem)
Next FolderItem

End Sub


Function GetFolder() As String
    Dim fldr As FileDialog
    Dim sItem As String
    Set fldr = Application.FileDialog(msoFileDialogFolderPicker)
    With fldr
        .Title = "Select a Folder"
        .AllowMultiSelect = False
        .InitialFileName = Application.DefaultFilePath
        If .Show <> -1 Then GoTo NextCode
        sItem = .SelectedItems(1)
    End With
NextCode:
    GetFolder = sItem
    Set fldr = Nothing
End Function

我得到了

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

它总是给我一个持续的答案。为什么?我确信&#34;角度&#34;和&#34; Kvalues&#34;正确计算数组。

以下是代码:

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

1 个答案:

答案 0 :(得分: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