Averages/Simple moving average: Difference between revisions
Content added Content deleted
(Updated both D entries, tags added) |
|||
Line 630: | Line 630: | ||
=={{header|D}}== |
=={{header|D}}== |
||
===Using a Closure=== |
|||
<lang d>import std.stdio, std.traits, std.algorithm; |
<lang d>import std.stdio, std.traits, std.algorithm; |
||
auto sma(T, int period)() { |
auto sma(T, int period)() { |
||
T[period] data = 0; // D FP are initialized to NaN |
T[period] data = 0; // D FP are default-initialized to NaN |
||
T sum = 0; |
T sum = 0; |
||
int index, nfilled; |
int index, nfilled; |
||
return (T v) { |
// return (in T v) nothrow { |
||
return delegate (in T v) nothrow { |
|||
sum += -data[index] + v; |
|||
data[index] |
sum += -data[index] + v; |
||
data[index] = v; |
|||
index = (index + 1) % period; |
|||
nfilled = min(period, nfilled + 1); |
|||
return cast(CommonType!(T, float))sum / nfilled; |
return cast(CommonType!(T, float))sum / nfilled; |
||
}; |
}; |
||
} |
} |
||
void main() { |
void main() { |
||
auto s3 = sma!(int, 3)(); |
auto s3 = sma!(int, 3)(); |
||
auto s5 = sma!(double, 5)(); |
auto s5 = sma!(double, 5)(); |
||
foreach (e; [1, 2, 3, 4, 5, 5, 4, 3, 2, 1]) |
foreach (e; [1, 2, 3, 4, 5, 5, 4, 3, 2, 1]) |
||
writefln("Added %d, sma(3) = %f, sma(5) = %f", |
writefln("Added %d, sma(3) = %f, sma(5) = %f", |
||
e, s3(e), s5(e)); |
|||
}</lang> |
}</lang> |
||
{{out}} |
|||
Output: |
|||
<pre>Added 1, sma(3) = 1.000000, sma(5) = 1.000000 |
<pre>Added 1, sma(3) = 1.000000, sma(5) = 1.000000 |
||
Added 2, sma(3) = 1.500000, sma(5) = 1.500000 |
Added 2, sma(3) = 1.500000, sma(5) = 1.500000 |
||
Line 664: | Line 667: | ||
Added 2, sma(3) = 3.000000, sma(5) = 3.800000 |
Added 2, sma(3) = 3.000000, sma(5) = 3.800000 |
||
Added 1, sma(3) = 2.000000, sma(5) = 3.000000</pre> |
Added 1, sma(3) = 2.000000, sma(5) = 3.000000</pre> |
||
===Using a Struct=== |
|||
This version avoids the heap allocation of the closure, same output: |
This version avoids the heap allocation of the closure, same output: |
||
<lang d>import std.stdio, std.traits, std.algorithm; |
<lang d>import std.stdio, std.traits, std.algorithm; |
||
struct SMA(T, int period) { |
struct SMA(T, int period) { |
||
T[period] data = 0; |
T[period] data = 0; |
||
T sum = 0; |
T sum = 0; |
||
int index, nfilled; |
int index, nfilled; |
||
auto opCall(T v) { |
auto opCall(in T v) pure nothrow { |
||
sum += -data[index] + v; |
sum += -data[index] + v; |
||
data[index] = v; |
data[index] = v; |
||
index = (index + 1) % period; |
index = (index + 1) % period; |
||
nfilled = min(period, nfilled + 1); |
nfilled = min(period, nfilled + 1); |
||
return cast(CommonType!(T, float))sum / nfilled; |
return cast(CommonType!(T, float))sum / nfilled; |
||
} |
} |
||
} |
} |
||
void main() { |
void main() { |
||
SMA!(int, 3) s3; |
SMA!(int, 3) s3; |
||
SMA!(double, 5) s5; |
SMA!(double, 5) s5; |
||
foreach (e; [1, 2, 3, 4, 5, 5, 4, 3, 2, 1]) |
foreach (e; [1, 2, 3, 4, 5, 5, 4, 3, 2, 1]) |
||
writefln("Added %d, sma(3) = %f, sma(5) = %f", |
writefln("Added %d, sma(3) = %f, sma(5) = %f", |
||
e, s3(e), s5(e)); |
|||
}</lang> |
}</lang> |
||
To avoid the floating point approximations keep piling up and growing, the code may perform a periodic sum on the whole circular queue array. |
To avoid the floating point approximations keep piling up and growing, the code may perform a periodic sum on the whole circular queue array. |