计算移动平均线在F#

编程入门 行业动态 更新时间:2024-10-26 08:32:17
本文介绍了计算移动平均线在F#的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

我还在上groking F#的东西 - 试图找出如何去思考F#中,而不是从其他语言我只知道翻译

I'm still working on groking the F# thing - trying to work out how to 'think' in F# rather than just translating from other languages I know.

我最近一直在思考,你没有1例:前后1的地图。情况下,List.map倒下。

I've recently been thinking about the cases where you don't have a 1:1 map between before and after. Cases where List.map falls down.

这方面的一个例子是移动平均线,在那里通常你会在n个项目均在+ 1结果长度LEN列表len个-N。

One example of this is moving averages, where typically you will have len-n+1 results for a list of length len when averaging over n items.

对于大师在那里,这是一个很好的方式(使用队列从乔莫·费舍尔)?

For the gurus out there, is this a good way to do it (using queue pinched from Jomo Fisher)?

//Immutable queue, with added Length member type Fifo<'a> = new()={xs=[];rxs=[]} new(xs,rxs)={xs=xs;rxs=rxs} val xs: 'a list; val rxs: 'a list; static member Empty() = new Fifo<'a>() member q.IsEmpty = (q.xs = []) && (q.rxs = []) member q.Enqueue(x) = Fifo(q.xs,x::q.rxs) member q.Length() = (List.length q.xs) + (List.length q.rxs) member q.Take() = if q.IsEmpty then failwith "fifo.Take: empty queue" else match q.xs with | [] -> (Fifo(List.rev q.rxs,[])).Take() | y::ys -> (Fifo(ys, q.rxs)),y //List module, add function to split one list into two parts (not safe if n > lst length) module List = let splitat n lst = let rec loop acc n lst = if List.length acc = n then (List.rev acc, lst) else loop (List.hd lst :: acc) n (List.tl lst) loop [] n lst //Return list with moving average accross len elements of lst let MovingAverage (len:int) (lst:float list) = //ugly mean - including this in Fifo kills genericity let qMean (q:Fifo<float>) = ((List.sum q.xs) + (List.sum q.rxs))/(float (q.Length())) //get first part of list to initialise queue let (init, rest) = List.splitat len lst //initialise queue with first n items let q = new Fifo<float>([], init) //loop through input list, use fifo to push/pull values as they come let rec loop (acc:float list) ls (q:Fifo<float>) = match ls with | [] -> List.rev acc | h::t -> let nq = q.Enqueue(h) //enqueue new value let (nq, _) = nq.Take() //drop old value loop ((qMean nq)::acc) t nq //tail recursion loop [qMean q] rest q //Example usage MovingAverage 3 [1.;1.;1.;1.;1.;2.;2.;2.;2.;2.]

(可能是更好的方式是由先进先出继承来实现MovingAverageQueue?)

(Maybe a better way would be to implement a MovingAverageQueue by inheriting from Fifo?)

推荐答案

如果你没有太在意性能,这里是一个非常简单的解决办法:

If you don't care too much about performance, here is a very simple solution:

#light let MovingAverage n s = Seq.windowed n s |> Seq.map Array.average let avgs = MovingAverage 5000 (Seq.map float [|1..999999|]) for avg in avgs do printfn "%f" avg System.Console.ReadKey() |> ignore

该重新计算每个从头开始'窗口'的平均值,因此它是可怜的,如果窗户都大。

This recomputes the average of each 'window' from scratch, so it is poor if the windows are large.

在任何情况下,请Seq.windowed:

In any case, check out Seq.windowed:

research.microsoft/projects/cambridge/fsharp/manual/FSharp.Core/Microsoft.FSharp.Collections.Seq.html

,因为它很方便的在你的后面的口袋里这样的事情。

as it's handy to have in your back pocket for such things.

更多推荐

计算移动平均线在F#

本文发布于:2023-10-15 02:30:46,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1492988.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:平均

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!