How to resolve the algorithm Averages/Simple moving average step by step in the C++ programming language
How to resolve the algorithm Averages/Simple moving average step by step in the C++ programming language
Table of Contents
Problem Statement
Computing the simple moving average of a series of numbers. Create a 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. 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:
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. Pseudo-code for an implementation of SMA is:
Let's start with the solution:
Step by Step solution about How to resolve the algorithm Averages/Simple moving average step by step in the C++ programming language
The provided C++ code demonstrates the implementation of a Simple Moving Average (SMA) algorithm for calculating the average of a sequence of values over a specified period. It involves a class named SMA
that manages the values and provides methods to add new values and calculate the average.
Class Definition:
The SMA
class has the following member variables and methods:
- Constructor: Initializes the SMA with a specified
period
(number of values to average over). It creates a dynamic array (window
) of double values, initializes thehead
andtail
pointers, and sets thetotal
to 0. - Destructor: Deallocates the dynamic array
window
. - add: Adds a new value to the average. It handles initialization and circular buffer management by advancing the
head
andtail
pointers as needed. - avg: Returns the average of the last
P
elements added to the SMA. If no elements have been added, it returns 0.0. - inc: Helper method that increments a pointer within the circular buffer, wrapping around if necessary.
- size: Helper method that returns the number of values stored in the SMA.
Main Function:
The main
function creates two instances of the SMA
class with periods of 3 and 5, respectively. It then iterates through an array of data values and adds them to the SMAs. After each addition, it prints the added value and the calculated average.
How it Works: The SMA algorithm maintains a circular buffer of values. As new values are added, the oldest value is removed from the buffer, and the new value is added to the end of the buffer. The average is then calculated as the sum of all values in the buffer divided by the number of values.
In this specific implementation, the head
and tail
pointers are used to keep track of the oldest and newest values in the buffer. The total
variable stores the sum of all values in the buffer to efficiently calculate the average without having to sum the entire buffer each time.
The code demonstrates the use of SMAs to calculate the average of data over different periods, showcasing how the average changes as new values are added.
Source code in the cpp programming language
#include <iostream>
#include <stddef.h>
#include <assert.h>
using std::cout;
using std::endl;
class SMA {
public:
SMA(unsigned int period) :
period(period), window(new double[period]), head(NULL), tail(NULL),
total(0) {
assert(period >= 1);
}
~SMA() {
delete[] window;
}
// Adds a value to the average, pushing one out if nescessary
void add(double val) {
// Special case: Initialization
if (head == NULL) {
head = window;
*head = val;
tail = head;
inc(tail);
total = val;
return;
}
// Were we already full?
if (head == tail) {
// Fix total-cache
total -= *head;
// Make room
inc(head);
}
// Write the value in the next spot.
*tail = val;
inc(tail);
// Update our total-cache
total += val;
}
// Returns the average of the last P elements added to this SMA.
// If no elements have been added yet, returns 0.0
double avg() const {
ptrdiff_t size = this->size();
if (size == 0) {
return 0; // No entries => 0 average
}
return total / (double) size; // Cast to double for floating point arithmetic
}
private:
unsigned int period;
double * window; // Holds the values to calculate the average of.
// Logically, head is before tail
double * head; // Points at the oldest element we've stored.
double * tail; // Points at the newest element we've stored.
double total; // Cache the total so we don't sum everything each time.
// Bumps the given pointer up by one.
// Wraps to the start of the array if needed.
void inc(double * & p) {
if (++p >= window + period) {
p = window;
}
}
// Returns how many numbers we have stored.
ptrdiff_t size() const {
if (head == NULL)
return 0;
if (head == tail)
return period;
return (period + tail - head) % period;
}
};
int main(int argc, char * * argv) {
SMA foo(3);
SMA bar(5);
int data[] = { 1, 2, 3, 4, 5, 5, 4, 3, 2, 1 };
for (int * itr = data; itr < data + 10; itr++) {
foo.add(*itr);
cout << "Added " << *itr << " avg: " << foo.avg() << endl;
}
cout << endl;
for (int * itr = data; itr < data + 10; itr++) {
bar.add(*itr);
cout << "Added " << *itr << " avg: " << bar.avg() << endl;
}
return 0;
}
You may also check:How to resolve the algorithm Loops/While step by step in the Retro programming language
You may also check:How to resolve the algorithm Text processing/2 step by step in the Ada programming language
You may also check:How to resolve the algorithm Word wrap step by step in the R programming language
You may also check:How to resolve the algorithm Substring/Top and tail step by step in the sed programming language
You may also check:How to resolve the algorithm Zig-zag matrix step by step in the PL/I programming language