I put together some code to calculate the moving average out of some sample data.
input is [12, 13, 15, 7, 6, 9, 13] output should be [12.5, 14, 11, 6.5, 7.5, 11]
int n = 2;
double[] data = { 12, 13, 15, 7, 6, 9, 13 };
double buffer[] = new double[n];
double output[] = new double[data.length];
int current_index = 0;
for (int i = 0; i < data.length; i ) {
buffer[current_index] = data[i] / n;
double ma = 0.0;
for (int j = 0; j < n; j ) {
ma = buffer[j];
}
output[i] = ma;
current_index= (current_index 1) % n;
}
//output: [6.0, 12.5, 14.0, 11.0, 6.5, 7.5, 11.0]
Does somebody know how i can get rid of output[0] (6.0)? this number should not be in the result.
Also how can i put the length of output[] to the real length of the output. so normally it should be:
double output[] = new double[data.length 1 - n];
but if i do this i get an indexoutofboundsexception.
CodePudding user response:
As you have less average than input values, you can't assign to output for each input, you need a condition
A condition that allows to wait to have passed enough values to start saving
for (int i = 0; i < data.length; i ) {
buffer[current_index] = data[i] / n;
double ma = 0.0;
for (int j = 0; j < n; j ) {
ma = buffer[j];
}
if (i >= (n - 1)) { // <<< <<<
output[i - n 1] = ma;
}
current_index = (current_index 1) % n;
}
Extracting to a method, then try all
static double[] movingAverage(double[] data, int n) {
double[] output = new double[data.length 1 - n];
double[] buffer = new double[n];
int current_index = 0;
for (int i = 0; i < data.length; i ) {
buffer[current_index] = data[i] / n;
double ma = 0.0;
for (int j = 0; j < n; j ) {
ma = buffer[j];
}
if (i >= (n - 1)) {
output[i - n 1] = ma;
}
current_index = (current_index 1) % n;
}
return output;
}
double[] data = {12, 13, 15, 7, 6, 9, 13};
for (int n = 1; n < data.length 1; n ) {
System.out.println(n " > " Arrays.toString(movingAverage(data, n)));
}
1 > [12.0, 13.0, 15.0, 7.0, 6.0, 9.0, 13.0]
2 > [12.5, 14.0, 11.0, 6.5, 7.5, 11.0]
3 > [13.333, 11.666, 9.333, 7.333, 9.333]
4 > [11.75, 10.25, 9.25, 8.75]
5 > [10.6, 10.0, 10.0]
6 > [10.333, 10.5]
7 > [10.714]
CodePudding user response:
You are correct that the following is the size of the array:
double output[] = new double[data.length 1 - n];
You could simplify this piece of code to something like:
public double[] movingAverage(double[] data, int n) {
double[] output = new double[data.length 1-n];
double runningSum = 0.0;
for (int i = 1; i <= data.length; i ) {
runningSum = data[i-1];
if (i >= n) {
double movingAverage = runningSum/n;
output[i-n] = movingAverage;
runningSum -= data[i-n];
}
}
return output;
}
This will reduce your time complexity from O(n^2) to O(n) also since there is just one for loop.
This type of algorithmic pattern is commonly referred to as Sliding Window approach.
CodePudding user response:
Simpler. You want a moving average of 2, it is very simple.
@Test
void test() {
double[] data = {12, 13, 15, 7, 6, 9, 13};
double output[] = new double[data.length - 1];
for (int i = 0; i < data.length - 1; i ) {
double k = (data[i] data[i 1]) / 2;
output[i] = k;
}
//output: [12.5, 14.0, 11.0, 6.5, 7.5, 11.0]
System.out.println(Arrays.toString(output));
}
If you want the moving average of n numbers, see test2:
@Test
void test2() {
int n = 3;
double[] data = {12, 13, 15, 7, 6, 9, 13};
double output[] = new double[data.length - (n - 1)];
for (int i = 0; i < data.length - (n - 1); i ) {
double buffer = 0;
for (int j = 0; j < n; j ) {
buffer = buffer data[i j];
}
output[i] = buffer / n;
}
//output: [13.333333333333334, 11.666666666666666, 9.333333333333334, 7.333333333333333, 9.333333333333334]
System.out.println(Arrays.toString(output));
}
If you can use java streams:
@Test
void test3(){
double[] data = {12, 13, 15, 7, 6, 9, 13};
final double[] output = IntStream.range(0, data.length - 1)
.mapToDouble(i -> (data[i] data[i 1]) / 2)
.toArray();
System.out.println(Arrays.toString(output));
}
After all, you just want the average over the sequencial next numbers.