I have a situation where I need to process 5000 samples from a device in every 0.5 sec.
Lets say the window size is 100, then there would be 50 points resulting from the moving average. I am trying with conventional method, i.e. with loops. But this is a very inefficient way to do it. Any suggestions ?
As we all know, calculating the average of a sequence is as simple as dividing the sum of all the elements by the number of elements. To calculate the average at index n given the average at index n-1 , we can multiply the old average by n-1 , add the new number, then divide that total by n .
IntStream average() method in Java The average() method of the IntStream class in Java returns an OptionalDouble describing the arithmetic mean of elements of this stream, or an empty optional if this stream is empty. It gets the average of the elements of the stream.
For each number in the array, add the number to sum. Compute average = sum / number of elements in array.
The Moving Average (MA) function computes the average of a set of input values over a specified number of periods. The smaller the number of periods, the faster the moving average responds to changes in the input values.
Check out the Apache Maths library. This has methods for doing precisely what you want. See DescriptiveStatistics and Mean for more info.
Here's one way.
public class Rolling { private int size; private double total = 0d; private int index = 0; private double samples[]; public Rolling(int size) { this.size = size; samples = new double[size]; for (int i = 0; i < size; i++) samples[i] = 0d; } public void add(double x) { total -= samples[index]; samples[index] = x; total += x; if (++index == size) index = 0; // cheaper than modulus } public double getAverage() { return total / size; } }
public class RollingTest extends TestCase { private final static int SIZE = 5; private static final double FULL_SUM = 12.5d; private Rolling r; public void setUp() { r = new Rolling(SIZE); } public void testInitial() { assertEquals(0d, r.getAverage()); } public void testOne() { r.add(3.5d); assertEquals(3.5d / SIZE, r.getAverage()); } public void testFillBuffer() { fillBufferAndTest(); } public void testForceOverWrite() { fillBufferAndTest(); double newVal = SIZE + .5d; r.add(newVal); // get the 'full sum' from fillBufferAndTest(), add the value we just added, // and subtract off the value we anticipate overwriting. assertEquals((FULL_SUM + newVal - .5d) / SIZE, r.getAverage()); } public void testManyValues() { for (int i = 0; i < 1003; i++) r.add((double) i); fillBufferAndTest(); } private void fillBufferAndTest() { // Don't write a zero value so we don't confuse an initialized // buffer element with a data element. for (int i = 0; i < SIZE; i++) r.add(i + .5d); assertEquals(FULL_SUM / SIZE, r.getAverage()); } }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With