我编写这个基-2 FFT的目的是在不牺牲太多性能的情况下使其功能地道:
let reverse x bits =
let rec reverse' x bits y =
match bits with
| 0 -> y
| _ -> ((y <<< 1) ||| (x &&& 1))
|> reverse' (x >>> 1) (bits - 1)
reverse' x bits 0
let radix2 (vector: Complex[]) (direction: int) =
let z = vector.Length
let depth = floor(Math.Log(double z, 2.0)) |> int
if (1 <<< depth) <> z then failwith "Vector length is not a power of 2"
// Complex roots of unity; "twiddle factors"
let unity: Complex[] =
let xpn = float direction * Math.PI / double z
Array.Parallel.init<Complex> (z/2) (fun i ->
Complex.FromPolarCoordinates(1.0, (float i) * xpn))
// Permutes elements of input vector via bit-reversal permutation
let pvec = Array.Parallel.init z (fun i -> vector.[reverse i depth])
let outerLoop (vec: Complex[]) =
let rec recLoop size =
if size <= z then
let mid, step = size / 2, z / size
let rec inrecLoop i =
if i < z then
let rec bottomLoop idx k =
if idx < i + mid then
let temp = vec.[idx + mid] * unity.[k]
vec.[idx + mid] <- (vec.[idx] - temp)
vec.[idx] <- (vec.[idx] + temp)
bottomLoop (idx + 1) (k + step)
bottomLoop i 0
inrecLoop (i + size)
inrecLoop 0
recLoop (size * 2)
recLoop 2
vec
outerLoop pvec
我不是算法工作的专家,所以可能有一个很好的函数实现,但值得注意的是,在F#中使用局部变异是非常惯用的。
您的radix2
函数是从外部起作用的--它将vector
数组作为输入,从不对其进行突变,创建一个新数组pvec
,然后对其进行初始化(沿途使用一些突变),然后返回它。这与array.map
等内置函数使用的模式类似(初始化一个新数组,对其进行突变,然后返回它)。这通常是一种明智的做法,因为有些算法更好地使用变异来编写。
在这种情况下,使用局部可变变量和循环是完全合理的。与尾递归版本相比,这样做将使您的代码更具可读性。我没有对此进行测试,但我对outerloop
函数的简单翻译就是使用三个嵌套循环--如下所示:
let mutable size = 2
while size <= z do
let mid, step = size / 2, z / size
let mutable i = 0
while i < z do
for j in 0 .. mid - 1 do
let idx, k = i + j, step * j
let temp = pvec.[idx + mid] * unity.[k]
pvec.[idx + mid] <- (pvec.[idx] - temp)
pvec.[idx] <- (pvec.[idx] + temp)
i <- i + size
size <- size * 2
这可能不完全正确(我这样做只是为了重构您的代码),但我认为在这种情况下,它实际上比使用复杂的嵌套尾递归函数更地道。
问题内容: 我有以下JavaScript代码: 我如何确保仅在完成后调用? 问题答案: 指定一个匿名回调,并使function1接受它:
Polar M600 有两个按钮:正面按钮与侧边电源按钮。 正面按钮 侧边电源按钮 触屏 前置按钮 在训练过程中使用正面按钮可轻易地启用 Polar 应用程式。您可使用正面按钮进行以下操作: 从主屏幕上迅速打开 Polar 应用程式 在 Polar 应用程式菜单中打开Training (训练)。 选择您想进行的运动并在运动内容列表中开始训练。 训练期间手动记圈。 暂停训练。 停止训练课。 训练结束
问题内容: 这段代码的结果为56。 知道里面发生了什么吗?我很困惑。 问题答案: X返回(值+3),而Y返回(值* 2) 给定值为4,这表示。 尽管函数不受范围限制(这意味着您可以安全地“嵌套”函数定义),但是此特定示例容易出错: 1)您不能在调用 之前先调用,因为函数只有执行一次才真正定义。 2)调用两次将导致PHP重新声明function ,从而导致致命错误: 致命错误:无法重新声明y() 两
Navicat Data Modeler 提供数种在创建模型时能改善用户体验的工具。 模型转换 自动布局 打印和导出模型 搜索筛选 全屏模式
Navicat Data Modeler 提供数种在创建模型时能改善用户体验的工具。 模型转换 自动布局 打印和导出模型 搜索筛选 深色布景主题 全屏模式
问题内容: 我正在开发一个Web应用程序,正在尝试为其提供功能齐全的窗口系统。目前进展顺利,我只遇到一个小问题。有时,当我去拖动应用程序的一部分时(通常是窗口的角落div,这应该触发调整大小的操作),Web浏览器变得很聪明,并认为我的意思是拖放东西。最终结果是,当浏览器进行拖放操作时,我的动作被暂停。 有没有一种简便的方法来禁用浏览器的拖放?理想情况下,我希望能够在用户单击某些元素时将其关闭,但是