F#棘手的递归算法

时间:2015-07-22 15:41:01

标签: list recursion f#

我在VBA中有这个代码(循环遍历double类型的数组a()):

   bm = 0                                       'tot
   b = 0                                        'prev
   For i = 24 To 0 Step -1
      BP = b                                    'prevprev = prev
      b = bm                                    'prev = tot
      bm = T * b - BP + a(i)                    'tot = a(i) + T * prev - prevprev
   Next
   p = Exp(-xa * xa) * (bm - BP) / 4            '* (tot - prevprev)/4

我把它放在F#中。显然,我可以使用数组和可变变量来重新创建VBA。也许这是我所见过的正确使用可变时间的一个例子。但为什么不尝试以最惯用的方式来做呢?

我可以编写一个小的递归函数来复制循环。但有点像乱扔垃圾,挂出一个没有任何意义的小循环作为一个独立的命名函数。

我想用List函数来做。我有几个想法,但我还没有。任何人都可以得到这个?

我有两个模糊的想法:1。我可以通过砍掉一个(和两个)元素并添加零值元素来制作另外两个列表。并结合这些列表。 2.我想知道像map这样的列表函数是否可以将列表中的尾随项作为参数。 3.作为一个普遍的问题,我想知道这可能是一个经验丰富的人会说这个问题为可变价值而尖叫的情况(如果这样做会削弱我对上功能船的热情)。

为代码提供更多直觉:摘录的完整函数是累积正态分布的数值近似。我没有抬头看看这个背后的数学。 " XA"是主函数参数的绝对值" x"这是从零开始的标准差的数量。如果不通过证明,我不会认为还有更多的话要说:它只是一个公式。 (哦,也许我应该更改变量名称 - xa和bm等非常糟糕。我确实把建议作为评论。)

3 个答案:

答案 0 :(得分:1)

这只是标准的递归。你做出退出条件和复发条件。

let rec calc i prevPrev prev total =
  if i = 0 then
    exp(-xa * xa) * (total - prevPrev) / 4.
  else 
    calc (i-1) prev total (T * total - prev + a i)

或更短......

n =input('write for nummbers ')
n=str(n)
i=0  
i+=1     #"i" show how many times iteration happend.
large = "".join(sorted(n, reverse=True))
little = "".join(sorted(n,))
n = int(large) - int(little)
print(n, i)

答案 1 :(得分:0)

这是我尝试将循环拉出作为递归函数。对于这个独立的家务,我并不感到激动,但我觉得语法很整洁。除了最后一行中的错误,也就是说,(c * a.Tail.Head)中的星号得到浮动列表的红色波浪线不匹配类型float(但我认为.Head必须返回float而不是列表):< / p>

let rec RecurseIt (a: float list) c  =
    match a with
    | []->              0.0
    | head::[]->        a.Head
    | head::tail::[]->  a.Head + (c * a.Tail) + (RecurseIt a.Tail c)                             
    | head::tail->      a.Head + (c * a.Tail.Head) - a.Tail.Tail.Head  + (RecurseIt a.Tail c) 

现在我将尝试列表功能。看起来我将不得不按元素迭代而不是找到一个一举的光滑方法。

另外我在这个递归函数中注意到我认为所有的递归调用都处于尾部位置 - 除了最后一个将提前一行。我想知道这是否会造成堆栈溢出风险(即,阻止编译器将递归视为循环(如果这是正确的描述),或者如果我仍然安全,因为算法将作为循环运行加上只有一个级别递归)。

编辑: 这是我试图返回列表而不是列表总和的方式(这样我可以使用第3个到最后一个元素并对元素求和),但是我已经离开了这个语法并且还在抨击它:< / p>

let rec RecurseIt (a: float list) c  =
    match a with
    | []->              []
    | head::[]->        [a.Head]
    | head::tail::[]->  [a.Head + (c * a.Tail)] :: (RecurseIt a.Tail c)                             
    | head::tail->      [a.Head + (c * a.Tail.Head) - a.Tail.Tail.Head]  :: (RecurseIt a.Tail c) 

答案 2 :(得分:0)

这是我在列表功能上的尝试。我认为这个问题比由于混淆我自己感觉更复杂。我刚才在List.iteri上有一些废话。希望这更接近有意义。我希望有些名单。功能会很整洁。没有管理。对于循环不是那么惯用我想。 :

for i in 0 .. a.Length - 1 do
    b:: 
        a.Item(i) +
            if i > 0 then
                T * b.Item(i-1) -
                    if i > 1 then
                        b.Item(i-2)
                    else
                        0
            else
                0