Averages/Simple moving average: Difference between revisions

Updated both D entries, tags added
(Updated both D entries, tags added)
Line 630:
 
=={{header|D}}==
===Using a Closure===
<lang d>import std.stdio, std.traits, std.algorithm;
 
auto sma(T, int period)() {
T[period] data = 0; // D FP are default-initialized to NaN
T sum = 0;
int index, nfilled;
 
// return (in T v) nothrow {
return delegate (in T v) nothrow {
sum += -data[index] + v;
sum += -data[index] =+ v;
index = (index + 1)data[index] %= periodv;
nfilled index = min(period, nfilledindex + 1) % period;
nfilled = min(period, nfilled + 1);
return cast(CommonType!(T, float))sum / nfilled;
};
}
 
void main() {
auto s3 = sma!(int, 3)();
auto s5 = sma!(double, 5)();
 
foreach (e; [1, 2, 3, 4, 5, 5, 4, 3, 2, 1])
writefln("Added %d, sma(3) = %f, sma(5) = %f", e, s3(e), s5(e));
e, s3(e), s5(e));
}</lang>
{{out}}
Output:
<pre>Added 1, sma(3) = 1.000000, sma(5) = 1.000000
Added 2, sma(3) = 1.500000, sma(5) = 1.500000
Line 664 ⟶ 667:
Added 2, sma(3) = 3.000000, sma(5) = 3.800000
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:
<lang d>import std.stdio, std.traits, std.algorithm;
 
struct SMA(T, int period) {
T[period] data = 0;
T sum = 0;
int index, nfilled;
 
auto opCall(in T v) pure nothrow {
sum += -data[index] + v;
data[index] = v;
index = (index + 1) % period;
nfilled = min(period, nfilled + 1);
return cast(CommonType!(T, float))sum / nfilled;
}
}
 
void main() {
SMA!(int, 3) s3;
SMA!(double, 5) s5;
 
foreach (e; [1, 2, 3, 4, 5, 5, 4, 3, 2, 1])
writefln("Added %d, sma(3) = %f, sma(5) = %f", e, s3(e), s5(e));
e, s3(e), s5(e));
}</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.