Add all the A tasks
This commit is contained in:
parent
2dd7375f96
commit
051504d65b
1608 changed files with 18584 additions and 0 deletions
33
Task/Averages-Simple-moving-average/0DESCRIPTION
Normal file
33
Task/Averages-Simple-moving-average/0DESCRIPTION
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
Computing the [[wp:Moving_average#Simple_moving_average|simple moving average]] of a series of numbers.
|
||||
|
||||
The task is to:
|
||||
:''Create a [[wp:Stateful|stateful]] function/class/instance that takes a period and returns a routine that takes a number as argument and returns a simple moving average of its arguments so far.''
|
||||
|
||||
'''Description'''<br>
|
||||
A simple moving average is a method for computing an average of a stream of numbers by only averaging the last P numbers from the stream, where P is known as the period. It can be implemented by calling an initialing routine with P as its argument, I(P), which should then return a routine that when called with individual, successive members of a stream of numbers, computes the mean of (up to), the last P of them, lets call this SMA().
|
||||
|
||||
The word stateful in the task description refers to the need for SMA() to remember certain information between calls to it:
|
||||
* The period, P
|
||||
* An ordered container of at least the last P numbers from each of its individual calls.
|
||||
Stateful also means that successive calls to I(), the initializer, should return separate routines that do ''not'' share saved state so they could be used on two independent streams of data.
|
||||
|
||||
Pseudocode for an implementation of SMA is:
|
||||
<pre>
|
||||
function SMA(number: N):
|
||||
stateful integer: P
|
||||
stateful list: stream
|
||||
number: average
|
||||
|
||||
stream.append_last(N)
|
||||
if stream.length() > P:
|
||||
# Only average the last P elements of the stream
|
||||
stream.delete_first()
|
||||
if stream.length() == 0:
|
||||
average = 0
|
||||
else:
|
||||
average = sum( stream.values() ) / stream.length()
|
||||
return average
|
||||
</pre>
|
||||
|
||||
|
||||
See also: [[Standard Deviation]]
|
||||
2
Task/Averages-Simple-moving-average/1META.yaml
Normal file
2
Task/Averages-Simple-moving-average/1META.yaml
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
---
|
||||
note: Probability and statistics
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
MODE SMAOBJ = STRUCT(
|
||||
LONG REAL sma,
|
||||
LONG REAL sum,
|
||||
INT period,
|
||||
REF[]LONG REAL values,
|
||||
INT lv
|
||||
);
|
||||
|
||||
MODE SMARESULT = UNION (
|
||||
REF SMAOBJ # handle #,
|
||||
LONG REAL # sma #,
|
||||
REF[]LONG REAL # values #
|
||||
);
|
||||
|
||||
MODE SMANEW = INT,
|
||||
SMAFREE = STRUCT(REF SMAOBJ free obj),
|
||||
SMAVALUES = STRUCT(REF SMAOBJ values obj),
|
||||
SMAADD = STRUCT(REF SMAOBJ add obj, LONG REAL v),
|
||||
SMAMEAN = STRUCT(REF SMAOBJ mean obj, REF[]LONG REAL v);
|
||||
|
||||
MODE ACTION = UNION ( SMANEW, SMAFREE, SMAVALUES, SMAADD, SMAMEAN );
|
||||
|
||||
PROC sma = ([]ACTION action)SMARESULT:
|
||||
(
|
||||
SMARESULT result;
|
||||
REF SMAOBJ obj;
|
||||
LONG REAL v;
|
||||
|
||||
FOR i FROM LWB action TO UPB action DO
|
||||
CASE action[i] IN
|
||||
(SMANEW period):( # args: INT period #
|
||||
HEAP SMAOBJ handle;
|
||||
sma OF handle := 0.0;
|
||||
period OF handle := period;
|
||||
values OF handle := HEAP [period OF handle]LONG REAL;
|
||||
lv OF handle := 0;
|
||||
sum OF handle := 0.0;
|
||||
result := handle
|
||||
),
|
||||
(SMAFREE args):( # args: REF SMAOBJ free obj #
|
||||
free obj OF args := REF SMAOBJ(NIL) # let the garbage collector do it's job #
|
||||
),
|
||||
(SMAVALUES args):( # args: REF SMAOBJ values obj #
|
||||
result := values OF values obj OF args
|
||||
),
|
||||
(SMAMEAN args):( # args: REF SMAOBJ mean obj #
|
||||
result := sma OF mean obj OF args
|
||||
),
|
||||
(SMAADD args):( # args: REF SMAOBJ add obj, LONG REAL v #
|
||||
obj := add obj OF args;
|
||||
v := v OF args;
|
||||
IF lv OF obj < period OF obj THEN
|
||||
(values OF obj)[lv OF obj+:=1] := v;
|
||||
sum OF obj +:= v;
|
||||
sma OF obj := sum OF obj / lv OF obj
|
||||
ELSE
|
||||
sum OF obj -:= (values OF obj)[ 1+ lv OF obj MOD period OF obj];
|
||||
sum OF obj +:= v;
|
||||
sma OF obj := sum OF obj / period OF obj;
|
||||
(values OF obj)[ 1+ lv OF obj MOD period OF obj ] := v; lv OF obj+:=1
|
||||
FI;
|
||||
result := sma OF obj
|
||||
)
|
||||
OUT
|
||||
SKIP
|
||||
ESAC
|
||||
OD;
|
||||
result
|
||||
);
|
||||
|
||||
[]LONG REAL v = ( 1, 2, 3, 4, 5, 5, 4, 3, 2, 1 );
|
||||
|
||||
main: (
|
||||
INT i;
|
||||
|
||||
REF SMAOBJ h3 := ( sma(SMANEW(3)) | (REF SMAOBJ obj):obj );
|
||||
REF SMAOBJ h5 := ( sma(SMANEW(5)) | (REF SMAOBJ obj):obj );
|
||||
|
||||
FOR i FROM LWB v TO UPB v DO
|
||||
printf(($"next number "g(0,6)", SMA_3 = "g(0,6)", SMA_5 = "g(0,6)l$,
|
||||
v[i], (sma(SMAADD(h3, v[i]))|(LONG REAL r):r), ( sma(SMAADD(h5, v[i])) | (LONG REAL r):r )
|
||||
))
|
||||
OD#;
|
||||
|
||||
sma(SMAFREE(h3));
|
||||
sma(SMAFREE(h5))
|
||||
#
|
||||
)
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
#!/usr/bin/awk -f
|
||||
# Moving average over the first column of a data file
|
||||
BEGIN {
|
||||
P = 5;
|
||||
}
|
||||
|
||||
{
|
||||
x = $1;
|
||||
i = NR % P;
|
||||
MA += (x - Z[i]) / P;
|
||||
Z[i] = x;
|
||||
print MA;
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
generic
|
||||
Max_Elements : Positive;
|
||||
type Number is digits <>;
|
||||
package Moving is
|
||||
procedure Add_Number (N : Number);
|
||||
function Moving_Average (N : Number) return Number;
|
||||
function Get_Average return Number;
|
||||
end Moving;
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
with Ada.Containers.Vectors;
|
||||
|
||||
package body Moving is
|
||||
use Ada.Containers;
|
||||
|
||||
package Number_Vectors is new Ada.Containers.Vectors
|
||||
(Element_Type => Number,
|
||||
Index_Type => Natural);
|
||||
|
||||
Current_List : Number_Vectors.Vector := Number_Vectors.Empty_Vector;
|
||||
|
||||
procedure Add_Number (N : Number) is
|
||||
begin
|
||||
if Natural (Current_List.Length) >= Max_Elements then
|
||||
Current_List.Delete_First;
|
||||
end if;
|
||||
Current_List.Append (N);
|
||||
end Add_Number;
|
||||
|
||||
function Get_Average return Number is
|
||||
Average : Number := 0.0;
|
||||
procedure Sum (Position : Number_Vectors.Cursor) is
|
||||
begin
|
||||
Average := Average + Number_Vectors.Element (Position);
|
||||
end Sum;
|
||||
begin
|
||||
Current_List.Iterate (Sum'Access);
|
||||
if Current_List.Length > 1 then
|
||||
Average := Average / Number (Current_List.Length);
|
||||
end if;
|
||||
return Average;
|
||||
end Get_Average;
|
||||
|
||||
function Moving_Average (N : Number) return Number is
|
||||
begin
|
||||
Add_Number (N);
|
||||
return Get_Average;
|
||||
end Moving_Average;
|
||||
|
||||
end Moving;
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
with Ada.Text_IO;
|
||||
with Moving;
|
||||
procedure Main is
|
||||
package Three_Average is new Moving (Max_Elements => 3, Number => Float);
|
||||
package Five_Average is new Moving (Max_Elements => 5, Number => Float);
|
||||
begin
|
||||
for I in 1 .. 5 loop
|
||||
Ada.Text_IO.Put_Line ("Inserting" & Integer'Image (I) &
|
||||
" into max-3: " & Float'Image (Three_Average.Moving_Average (Float (I))));
|
||||
Ada.Text_IO.Put_Line ("Inserting" & Integer'Image (I) &
|
||||
" into max-5: " & Float'Image (Five_Average.Moving_Average (Float (I))));
|
||||
end loop;
|
||||
for I in reverse 1 .. 5 loop
|
||||
Ada.Text_IO.Put_Line ("Inserting" & Integer'Image (I) &
|
||||
" into max-3: " & Float'Image (Three_Average.Moving_Average (Float (I))));
|
||||
Ada.Text_IO.Put_Line ("Inserting" & Integer'Image (I) &
|
||||
" into max-5: " & Float'Image (Five_Average.Moving_Average (Float (I))));
|
||||
end loop;
|
||||
end Main;
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
MsgBox % MovingAverage(5,3) ; 5, averaging length <- 3
|
||||
MsgBox % MovingAverage(1) ; 3
|
||||
MsgBox % MovingAverage(-3) ; 1
|
||||
MsgBox % MovingAverage(8) ; 2
|
||||
MsgBox % MovingAverage(7) ; 4
|
||||
|
||||
MovingAverage(x,len="") { ; for integers (faster)
|
||||
Static
|
||||
Static sum:=0, n:=0, m:=10 ; default averaging length = 10
|
||||
If (len>"") ; non-blank 2nd parameter: set length, reset
|
||||
sum := n := i := 0, m := len
|
||||
If (n < m) ; until the buffer is not full
|
||||
sum += x, n++ ; keep summing data
|
||||
Else ; when buffer is full
|
||||
sum += x-v%i% ; add new, subtract oldest
|
||||
v%i% := x, i := mod(i+1,m) ; remember last m inputs, cycle insertion point
|
||||
Return sum/n
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
MovingAverage(x,len="") { ; for floating point numbers
|
||||
Static
|
||||
Static n:=0, m:=10 ; default averaging length = 10
|
||||
If (len>"") ; non-blank 2nd parameter: set length, reset
|
||||
n := i := 0, m := len
|
||||
n += n < m, sum := 0
|
||||
v%i% := x, i := mod(i+1,m) ; remember last m inputs, cycle insertion point
|
||||
Loop %n% ; recompute sum to avoid error accumulation
|
||||
j := A_Index-1, sum += v%j%
|
||||
Return sum/n
|
||||
}
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
typedef struct sma_obj {
|
||||
double sma;
|
||||
double sum;
|
||||
int period;
|
||||
double *values;
|
||||
int lv;
|
||||
} sma_obj_t;
|
||||
|
||||
typedef union sma_result {
|
||||
sma_obj_t *handle;
|
||||
double sma;
|
||||
double *values;
|
||||
} sma_result_t;
|
||||
|
||||
enum Action { SMA_NEW, SMA_FREE, SMA_VALUES, SMA_ADD, SMA_MEAN };
|
||||
sma_result_t sma(enum Action action, ...)
|
||||
{
|
||||
va_list vl;
|
||||
sma_result_t r;
|
||||
sma_obj_t *o;
|
||||
double v;
|
||||
|
||||
va_start(vl, action);
|
||||
switch(action) {
|
||||
case SMA_NEW: // args: int period
|
||||
r.handle = malloc(sizeof(sma_obj_t));
|
||||
r.handle->sma = 0.0;
|
||||
r.handle->period = va_arg(vl, int);
|
||||
r.handle->values = malloc(r.handle->period * sizeof(double));
|
||||
r.handle->lv = 0;
|
||||
r.handle->sum = 0.0;
|
||||
break;
|
||||
case SMA_FREE: // args: sma_obj_t *handle
|
||||
r.handle = va_arg(vl, sma_obj_t *);
|
||||
free(r.handle->values);
|
||||
free(r.handle);
|
||||
r.handle = NULL;
|
||||
break;
|
||||
case SMA_VALUES: // args: sma_obj_t *handle
|
||||
o = va_arg(vl, sma_obj_t *);
|
||||
r.values = o->values;
|
||||
break;
|
||||
case SMA_MEAN: // args: sma_obj_t *handle
|
||||
o = va_arg(vl, sma_obj_t *);
|
||||
r.sma = o->sma;
|
||||
break;
|
||||
case SMA_ADD: // args: sma_obj_t *handle, double value
|
||||
o = va_arg(vl, sma_obj_t *);
|
||||
v = va_arg(vl, double);
|
||||
if ( o->lv < o->period ) {
|
||||
o->values[o->lv++] = v;
|
||||
o->sum += v;
|
||||
o->sma = o->sum / o->lv;
|
||||
} else {
|
||||
o->sum -= o->values[ o->lv % o->period];
|
||||
o->sum += v;
|
||||
o->sma = o->sum / o->period;
|
||||
o->values[ o->lv % o->period ] = v; o->lv++;
|
||||
}
|
||||
r.sma = o->sma;
|
||||
break;
|
||||
}
|
||||
va_end(vl);
|
||||
return r;
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
double v[] = { 1, 2, 3, 4, 5, 5, 4, 3, 2, 1 };
|
||||
|
||||
int main()
|
||||
{
|
||||
int i;
|
||||
|
||||
sma_obj_t *h3 = sma(SMA_NEW, 3).handle;
|
||||
sma_obj_t *h5 = sma(SMA_NEW, 5).handle;
|
||||
|
||||
for(i=0; i < sizeof(v)/sizeof(double) ; i++) {
|
||||
printf("next number %lf, SMA_3 = %lf, SMA_5 = %lf\n",
|
||||
v[i], sma(SMA_ADD, h3, v[i]).sma, sma(SMA_ADD, h5, v[i]).sma);
|
||||
}
|
||||
|
||||
sma(SMA_FREE, h3);
|
||||
sma(SMA_FREE, h5);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
(import '[clojure.lang PersistentQueue])
|
||||
|
||||
(defn enqueue-max [q p n]
|
||||
(let [q (conj q n)]
|
||||
(if (<= (count q) p) q (pop q))))
|
||||
|
||||
(defn avg [coll] (/ (reduce + coll) (count coll)))
|
||||
|
||||
(defn init-moving-avg [p]
|
||||
(let [state (atom PersistentQueue/EMPTY)]
|
||||
(fn [n]
|
||||
(avg (swap! state enqueue-max p n)))))
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
I = (P) ->
|
||||
# The cryptic name "I" follows the problem description;
|
||||
# it returns a function that computes a moving average
|
||||
# of successive values over the period P, using closure
|
||||
# variables to maintain state.
|
||||
cq = circular_queue(P)
|
||||
num_elems = 0
|
||||
sum = 0
|
||||
|
||||
SMA = (n) ->
|
||||
sum += n
|
||||
if num_elems < P
|
||||
cq.add(n)
|
||||
num_elems += 1
|
||||
sum / num_elems
|
||||
else
|
||||
old = cq.replace(n)
|
||||
sum -= old
|
||||
sum / P
|
||||
|
||||
circular_queue = (n) ->
|
||||
# queue that only ever stores up to n values;
|
||||
# Caller shouldn't call replace until n values
|
||||
# have been added.
|
||||
i = 0
|
||||
arr = []
|
||||
|
||||
add: (elem) ->
|
||||
arr.push elem
|
||||
replace: (elem) ->
|
||||
# return value whose age is "n"
|
||||
old_val = arr[i]
|
||||
arr[i] = elem
|
||||
i = (i + 1) % n
|
||||
old_val
|
||||
|
||||
# The output of the code below should convince you that
|
||||
# calling I multiple times returns functions with independent
|
||||
# state.
|
||||
sma3 = I(3)
|
||||
sma7 = I(7)
|
||||
sma11 = I(11)
|
||||
for i in [1..10]
|
||||
console.log i, sma3(i), sma7(i), sma11(i)
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
> coffee moving_average.coffee
|
||||
1 1 1 1
|
||||
2 1.5 1.5 1.5
|
||||
3 2 2 2
|
||||
4 3 2.5 2.5
|
||||
5 4 3 3
|
||||
6 5 3.5 3.5
|
||||
7 6 4 4
|
||||
8 7 5 4.5
|
||||
9 8 6 5
|
||||
10 9 7 5.5
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
main() ->
|
||||
SMA3 = sma(3),
|
||||
SMA5 = sma(5),
|
||||
Ns = [1, 2, 3, 4, 5, 5, 4, 3, 2, 1],
|
||||
lists:foreach(
|
||||
fun (N) ->
|
||||
io:format("Added ~b, sma(3) -> ~f, sma(5) -> ~f~n",[N,next(SMA3,N),next(SMA5,N)])
|
||||
end, Ns),
|
||||
stop(SMA3),
|
||||
stop(SMA5).
|
||||
|
||||
sma(W) ->
|
||||
{sma,spawn(?MODULE,loop,[W,[]])}.
|
||||
|
||||
loop(Window, Numbers) ->
|
||||
receive
|
||||
{_Pid, stop} ->
|
||||
ok;
|
||||
{Pid, N} when is_number(N) ->
|
||||
case length(Numbers) < Window of
|
||||
true ->
|
||||
Next = Numbers++[N];
|
||||
false ->
|
||||
Next = tl(Numbers)++[N]
|
||||
end,
|
||||
Pid ! {average, lists:sum(Next)/length(Next)},
|
||||
loop(Window,Next);
|
||||
_ ->
|
||||
ok
|
||||
end.
|
||||
|
||||
stop({sma,Pid}) ->
|
||||
Pid ! {self(),stop},
|
||||
ok.
|
||||
|
||||
next({sma,Pid},N) ->
|
||||
Pid ! {self(), N},
|
||||
receive
|
||||
{average, Ave} ->
|
||||
Ave
|
||||
end.
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
9> sma:main().
|
||||
Added 1, sma(3) -> 1.000000, sma(5) -> 1.000000
|
||||
Added 2, sma(3) -> 1.500000, sma(5) -> 1.500000
|
||||
Added 3, sma(3) -> 2.000000, sma(5) -> 2.000000
|
||||
Added 4, sma(3) -> 3.000000, sma(5) -> 2.500000
|
||||
Added 5, sma(3) -> 4.000000, sma(5) -> 3.000000
|
||||
Added 5, sma(3) -> 4.666667, sma(5) -> 3.800000
|
||||
Added 4, sma(3) -> 4.666667, sma(5) -> 4.200000
|
||||
Added 3, sma(3) -> 4.000000, sma(5) -> 4.200000
|
||||
Added 2, sma(3) -> 3.000000, sma(5) -> 3.800000
|
||||
Added 1, sma(3) -> 2.000000, sma(5) -> 3.000000
|
||||
ok
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
: f+! ( f addr -- ) dup f@ f+ f! ;
|
||||
: ,f0s ( n -- ) falign 0 do 0e f, loop ;
|
||||
|
||||
: period @ ;
|
||||
: used cell+ ;
|
||||
: head 2 cells + ;
|
||||
: sum 3 cells + faligned ;
|
||||
: ring ( addr -- faddr )
|
||||
dup sum float+ swap head @ floats + ;
|
||||
|
||||
: update ( fvalue addr -- addr )
|
||||
dup ring f@ fnegate dup sum f+!
|
||||
fdup dup ring f! dup sum f+!
|
||||
dup head @ 1+ over period mod over head ! ;
|
||||
|
||||
: moving-average
|
||||
create ( period -- ) dup , 0 , 0 , 1+ ,f0s
|
||||
does> ( fvalue -- avg )
|
||||
update
|
||||
dup used @ over period < if 1 over used +! then
|
||||
dup sum f@ used @ 0 d>f f/ ;
|
||||
|
||||
3 moving-average sma
|
||||
1e sma f. \ 1.
|
||||
2e sma f. \ 1.5
|
||||
3e sma f. \ 2.
|
||||
4e sma f. \ 3.
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
program Movavg
|
||||
implicit none
|
||||
|
||||
integer :: i
|
||||
|
||||
write (*, "(a)") "SIMPLE MOVING AVERAGE: PERIOD = 3"
|
||||
|
||||
do i = 1, 5
|
||||
write (*, "(a, i2, a, f8.6)") "Next number:", i, " sma = ", sma(real(i))
|
||||
end do
|
||||
do i = 5, 1, -1
|
||||
write (*, "(a, i2, a, f8.6)") "Next number:", i, " sma = ", sma(real(i))
|
||||
end do
|
||||
|
||||
contains
|
||||
|
||||
function sma(n)
|
||||
real :: sma
|
||||
real, intent(in) :: n
|
||||
real, save :: a(3) = 0
|
||||
integer, save :: count = 0
|
||||
|
||||
if (count < 3) then
|
||||
count = count + 1
|
||||
a(count) = n
|
||||
else
|
||||
a = eoshift(a, 1, n)
|
||||
end if
|
||||
|
||||
sma = sum(a(1:count)) / real(count)
|
||||
end function
|
||||
|
||||
end program Movavg
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func sma(n int) func(float64) float64 {
|
||||
s := make([]float64, 0, n)
|
||||
i, sum, rn := 0, 0., 1/float64(n)
|
||||
return func(x float64) float64 {
|
||||
if len(s) < n {
|
||||
sum += x
|
||||
s = append(s, x)
|
||||
return sum / float64(len(s))
|
||||
}
|
||||
s[i] = x
|
||||
i++
|
||||
if i == n {
|
||||
i = 0
|
||||
}
|
||||
sum = 0
|
||||
for _, x = range s {
|
||||
sum += x
|
||||
}
|
||||
return sum * rn
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
sma3 := sma(3)
|
||||
sma5 := sma(5)
|
||||
fmt.Println("x sma3 sma5")
|
||||
for _, x := range []float64{1, 2, 3, 4, 5, 5, 4, 3, 2, 1} {
|
||||
fmt.Printf("%5.3f %5.3f %5.3f\n", x, sma3(x), sma5(x))
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
import Data.List
|
||||
import Control.Arrow
|
||||
import Control.Monad
|
||||
|
||||
sMA p = map (head *** head ).tail.
|
||||
scanl (\(y,_) -> (id &&& return. av) . (: if length y == p then init y else y)) ([],[])
|
||||
where av = liftM2 (/) sum (fromIntegral.length)
|
||||
|
||||
printSMA n p = mapM_ (\(n,a) -> putStrLn $ "Next number: " ++ show n ++ " Average: " ++ show a)
|
||||
. take n . sMA p $ [1..5]++[5,4..1]++[3..]
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
import java.util.LinkedList;
|
||||
import java.util.Queue;
|
||||
public class MovingAverage {
|
||||
private final Queue<Double> window = new LinkedList<Double>();
|
||||
private final int period;
|
||||
private double sum;
|
||||
|
||||
public MovingAverage(int period) {
|
||||
assert period > 0 : "Period must be a positive integer";
|
||||
this.period = period;
|
||||
}
|
||||
|
||||
public void newNum(double num) {
|
||||
sum += num;
|
||||
window.add(num);
|
||||
if (window.size() > period) {
|
||||
sum -= window.remove();
|
||||
}
|
||||
}
|
||||
|
||||
public double getAvg() {
|
||||
if (window.isEmpty()) return 0; // technically the average is undefined
|
||||
return sum / window.size();
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
double[] testData = {1,2,3,4,5,5,4,3,2,1};
|
||||
int[] windowSizes = {3,5};
|
||||
for (int windSize : windowSizes) {
|
||||
MovingAverage ma = new MovingAverage(windSize);
|
||||
for (double x : testData) {
|
||||
ma.newNum(x);
|
||||
System.out.println("Next number = " + x + ", SMA = " + ma.getAvg());
|
||||
}
|
||||
System.out.println();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
function simple_moving_averager(period) {
|
||||
var nums = [];
|
||||
return function(num) {
|
||||
nums.push(num);
|
||||
if (nums.length > period)
|
||||
nums.splice(0,1); // remove the first element of the array
|
||||
var sum = 0;
|
||||
for (var i in nums)
|
||||
sum += nums[i];
|
||||
var n = period;
|
||||
if (nums.length < period)
|
||||
n = nums.length;
|
||||
return(sum/n);
|
||||
}
|
||||
}
|
||||
|
||||
var sma3 = simple_moving_averager(3);
|
||||
var sma5 = simple_moving_averager(5);
|
||||
var data = [1,2,3,4,5,5,4,3,2,1];
|
||||
for (var i in data) {
|
||||
var n = data[i];
|
||||
// using WSH
|
||||
WScript.Echo("Next number = " + n + ", SMA_3 = " + sma3(n) + ", SMA_5 = " + sma5(n));
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
do
|
||||
local t = {}
|
||||
function f(a, b, ...) if b then return f(a+b, ...) else return a end end
|
||||
function average(n)
|
||||
if #t == 10 then table.remove(t, 1) end
|
||||
t[#t + 1] = n
|
||||
return f(unpack(t)) / #t
|
||||
end
|
||||
end
|
||||
for v=1,30 do print(average(v)) end
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
sub sma ($)
|
||||
{my ($period, $sum, @a) = shift, 0;
|
||||
return sub
|
||||
{unshift @a, shift;
|
||||
$sum += $a[0];
|
||||
@a > $period and $sum -= pop @a;
|
||||
return $sum / @a;}}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
(de sma (@Len)
|
||||
(curry (@Len (Data)) (N)
|
||||
(push 'Data N)
|
||||
(and (nth Data @Len) (con @)) # Truncate
|
||||
(*/ (apply + Data) (length Data)) ) )
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
(def 'sma3 (sma 3))
|
||||
(def 'sma5 (sma 5))
|
||||
|
||||
(scl 2)
|
||||
(for N (1.0 2.0 3.0 4.0 5.0 5.0 4.0 3.0 2.0 1.0)
|
||||
(prinl
|
||||
(format N *Scl)
|
||||
" (sma3) "
|
||||
(format (sma3 N) *Scl)
|
||||
" (sma5) "
|
||||
(format (sma5 N) *Scl) ) )
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
from collections import deque
|
||||
|
||||
def simplemovingaverage(period):
|
||||
assert period == int(period) and period > 0, "Period must be an integer >0"
|
||||
|
||||
summ = n = 0.0
|
||||
values = deque([0.0] * period) # old value queue
|
||||
|
||||
def sma(x):
|
||||
nonlocal summ, n
|
||||
|
||||
values.append(x)
|
||||
summ += x - values.popleft()
|
||||
n = min(n+1, period)
|
||||
return summ / n
|
||||
|
||||
return sma
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
from collections import deque
|
||||
|
||||
class Simplemovingaverage():
|
||||
def __init__(self, period):
|
||||
assert period == int(period) and period > 0, "Period must be an integer >0"
|
||||
self.period = period
|
||||
self.stream = deque()
|
||||
|
||||
def __call__(self, n):
|
||||
stream = self.stream
|
||||
stream.append(n) # appends on the right
|
||||
streamlength = len(stream)
|
||||
if streamlength > self.period:
|
||||
stream.popleft()
|
||||
streamlength -= 1
|
||||
if streamlength == 0:
|
||||
average = 0
|
||||
else:
|
||||
average = sum( stream ) / streamlength
|
||||
|
||||
return average
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
if __name__ == '__main__':
|
||||
for period in [3, 5]:
|
||||
print ("\nSIMPLE MOVING AVERAGE (procedural): PERIOD =", period)
|
||||
sma = simplemovingaverage(period)
|
||||
for i in range(1,6):
|
||||
print (" Next number = %-2g, SMA = %g " % (i, sma(i)))
|
||||
for i in range(5, 0, -1):
|
||||
print (" Next number = %-2g, SMA = %g " % (i, sma(i)))
|
||||
for period in [3, 5]:
|
||||
print ("\nSIMPLE MOVING AVERAGE (class based): PERIOD =", period)
|
||||
sma = Simplemovingaverage(period)
|
||||
for i in range(1,6):
|
||||
print (" Next number = %-2g, SMA = %g " % (i, sma(i)))
|
||||
for i in range(5, 0, -1):
|
||||
print (" Next number = %-2g, SMA = %g " % (i, sma(i)))
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
#concat concatenates the new values to the existing vector of values, then discards any values that are too old.
|
||||
lastvalues <- local(
|
||||
{
|
||||
values <- c();
|
||||
function(x, len)
|
||||
{
|
||||
values <<- c(values, x);
|
||||
lenv <- length(values);
|
||||
if(lenv > len) values <<- values[(len-lenv):-1]
|
||||
values
|
||||
}
|
||||
})
|
||||
|
||||
#moving.average accepts a numeric scalars input (and optionally a length, i.e. the number of values to retain) and calculates the stateful moving average.
|
||||
moving.average <- function(latestvalue, len=3)
|
||||
{
|
||||
#Check that all inputs are numeric scalars
|
||||
is.numeric.scalar <- function(x) is.numeric(x) && length(x)==1L
|
||||
if(!is.numeric.scalar(latestvalue) || !is.numeric.scalar(len))
|
||||
{
|
||||
stop("all arguments must be numeric scalars")
|
||||
}
|
||||
|
||||
#Calculate mean of variables so far
|
||||
mean(lastvalues(latestvalue, len))
|
||||
}
|
||||
moving.average(5) # 5
|
||||
moving.average(1) # 3
|
||||
moving.average(-3) # 1
|
||||
moving.average(8) # 2
|
||||
moving.average(7) # 4
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
/*REXX program is illustrate simple moving average. */
|
||||
arg p q n . /*get some arguments (maybe). */
|
||||
if p=='' then p=3 /*the 1st period (default: 3).*/
|
||||
if q=='' then q=5 /* " 2nd " " 5 */
|
||||
if n=='' then n=10 /*number of items in the list.*/
|
||||
a.=0
|
||||
do j=1 for n%2 /*build beginning of the list,*/
|
||||
a.j=j /* ... increasing values. */
|
||||
end /*j*/
|
||||
|
||||
do k=n%2 to 1 by -1 /* ... decreasing values. */
|
||||
a.j=k
|
||||
j=j+1
|
||||
end /*k*/
|
||||
|
||||
do i=1 for n /*show an indented item list. */
|
||||
say left('',60) 'item' right(i,3)'='right(a.i,3)
|
||||
end /*i*/
|
||||
do m=1 for n /*OK the, let's start the SMA.*/
|
||||
smaP=sma(p,m) /*simple moving average for P.*/
|
||||
smaQ=sma(q,m) /* " " " " Q.*/
|
||||
|
||||
/*show 2 nicely formated SMAs.*/
|
||||
say 'm='right(m,3), /*show where we're at in list.*/
|
||||
" sma("p')='left(sma(p,m),11), /*show nicely aligned sma P. */
|
||||
" sma("q')='left(sma(q,m),11) /* " " " " Q. */
|
||||
end /*m*/
|
||||
exit
|
||||
/*────────────────────────────────────────SMA subroutine────────────────*/
|
||||
sma: procedure expose A.; arg p,j; s=0; i=0
|
||||
do k=max(1,j-p+1) to j+p for p while k<=j
|
||||
i=i+1
|
||||
s=s+a.k
|
||||
end
|
||||
return s/i
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
def simple_moving_average(size)
|
||||
nums = []
|
||||
sum = 0.0
|
||||
lambda do |hello|
|
||||
nums << hello
|
||||
goodbye = nums.length > size ? nums.shift : 0
|
||||
sum += hello - goodbye
|
||||
sum / nums.length
|
||||
end
|
||||
end
|
||||
|
||||
ma3 = simple_moving_average(3)
|
||||
ma5 = simple_moving_average(5)
|
||||
|
||||
(1.upto(5).to_a + 5.downto(1).to_a).each do |num|
|
||||
printf "Next number = %d, SMA_3 = %.3f, SMA_5 = %.1f\n",
|
||||
num, ma3.call(num), ma5.call(num)
|
||||
end
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
class MovingAverager
|
||||
def initialize(size)
|
||||
@size = size
|
||||
@nums = []
|
||||
@sum = 0.0
|
||||
end
|
||||
def <<(hello)
|
||||
@nums << hello
|
||||
goodbye = @nums.length > @size ? @nums.shift : 0
|
||||
@sum += hello - goodbye
|
||||
self
|
||||
end
|
||||
def average
|
||||
@sum / @nums.length
|
||||
end
|
||||
alias to_f average
|
||||
def to_s
|
||||
average.to_s
|
||||
end
|
||||
end
|
||||
|
||||
ma3 = MovingAverager.new(3)
|
||||
ma5 = MovingAverager.new(5)
|
||||
|
||||
(1.upto(5).to_a + 5.downto(1).to_a).each do |num|
|
||||
printf "Next number = %d, SMA_3 = %.3f, SMA_5 = %.1f\n",
|
||||
num, ma3 << num, ma5 <<num
|
||||
end
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
class MovingAverage(period: Int) {
|
||||
private var queue = new scala.collection.mutable.Queue[Double]()
|
||||
def apply(n: Double) = {
|
||||
queue.enqueue(n)
|
||||
if (queue.size > period)
|
||||
queue.dequeue
|
||||
queue.sum / queue.size
|
||||
}
|
||||
override def toString = queue.mkString("(", ", ", ")")+", period "+period+", average "+(queue.sum / queue.size)
|
||||
def clear = queue.clear
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
(define ((simple-moving-averager size . nums) num)
|
||||
(set! nums (cons num (if (= (length nums) size) (reverse (cdr (reverse nums))) nums)))
|
||||
(/ (apply + nums) (length nums)))
|
||||
|
||||
(define av (simple-moving-averager 3))
|
||||
(map av '(1 2 3 4 5 5 4 3 2 1))
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
Object subclass: MovingAverage [
|
||||
|valueCollection period collectedNumber sum|
|
||||
MovingAverage class >> newWithPeriod: thePeriod [
|
||||
|r|
|
||||
r := super basicNew.
|
||||
^ r initWithPeriod: thePeriod
|
||||
]
|
||||
initWithPeriod: thePeriod [
|
||||
valueCollection := OrderedCollection new: thePeriod.
|
||||
period := thePeriod.
|
||||
collectedNumber := 0.
|
||||
sum := 0
|
||||
]
|
||||
sma [ collectedNumber < period
|
||||
ifTrue: [ ^ sum / collectedNumber ]
|
||||
ifFalse: [ ^ sum / period ] ]
|
||||
add: value [
|
||||
collectedNumber < period
|
||||
ifTrue: [
|
||||
sum := sum + value.
|
||||
valueCollection add: value.
|
||||
collectedNumber := collectedNumber + 1.
|
||||
]
|
||||
ifFalse: [
|
||||
sum := sum - (valueCollection removeFirst).
|
||||
sum := sum + value.
|
||||
valueCollection add: value
|
||||
].
|
||||
^ self sma
|
||||
]
|
||||
].
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
|sma3 sma5|
|
||||
|
||||
sma3 := MovingAverage newWithPeriod: 3.
|
||||
sma5 := MovingAverage newWithPeriod: 5.
|
||||
|
||||
#( 1 2 3 4 5 5 4 3 2 1 ) do: [ :v |
|
||||
('Next number %1, SMA_3 = %2, SMA_5 = %3' % {
|
||||
v . (sma3 add: v) asFloat . (sma5 add: v) asFloat
|
||||
}) displayNl
|
||||
]
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
oo::class create SimpleMovingAverage {
|
||||
variable vals idx
|
||||
constructor {{period 3}} {
|
||||
set idx end-[expr {$period-1}]
|
||||
set vals {}
|
||||
}
|
||||
method val x {
|
||||
set vals [lrange [list {*}$vals $x] $idx end]
|
||||
expr {[tcl::mathop::+ {*}$vals]/double([llength $vals])}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
SimpleMovingAverage create averager3
|
||||
SimpleMovingAverage create averager5 5
|
||||
foreach n {1 2 3 4 5 5 4 3 2 1} {
|
||||
puts "Next number = $n, SMA_3 = [averager3 val $n], SMA_5 = [averager5 val $n]"
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue