2013-10-04 2 views
0

Мне нужна программа, которая будет вычислять скользящее среднее набора чисел (я использовал 4, 9, 3.14, 1.59, 86.0, 35.2, 9.98, 1.00, 0.01, 2.2, и 3.76). Когда я запускаю это, он печатает «17.859999999999996» девять раз. Вы видите ошибки?Как создать скользящее среднее в Java

import java.util.*; 

public class MovingAverage 
{ 
    public static void main(String args[]) 
    { 
     Scanner scan = new Scanner(System.in); 
     // Read in the length of the moving average and the number 
     // of data points 
     int averageLength = scan.nextInt(); 
     int numDataPoints = scan.nextInt(); 
     // Create an array to hold the data points, and another to 
     // hold the moving average 
     double data[] = new double[numDataPoints]; 
     double movingAverage[] = new double[numDataPoints]; 
     // Read in all of the data points using a for loop 
     for(int i = 0; i< numDataPoints; i++) 
     { 
      data[i]=scan.nextDouble(); 
     } 
     // Create the moving average 
     for (int i=0; i<numDataPoints; i++) 
     { 
      // Calculate the moving average for index i and put 
      // it in movingAverage[i]. (Hint: you need a for 
      // loop to do this. Make sure not to use i as your 
      // loop variable. Also, make sure to handle the 
      // case where i is not large enough (when i<averageLength-1). 
      double sum= 0.0; 
      for(int j=0; j<numDataPoints; j++) 
      { 

       sum=sum+data[j]; 
       movingAverage[i]=sum/j; 
      } 

     } 
     // Print the moving average, one value per line 
     for (int i=0; i<numDataPoints; i++) 
     { 
      System.out.println(movingAverage[i]); 
     } 
    } 
} 
+1

Когда вы просматриваете программу с помощью отладчика или вставляете вызовы 'println' в цикле для просмотра промежуточных значений, что вы видите? – Simon

ответ

0

Вы каждый раз перебираете все данные. Вы должны иметь for(int j=(i>=averageLength?i-averageLength/2:0); j< i+averageLength/2 && j<numDataPoints; j++) (или что-то подобное) для вашего сокровенного среднего.

Также необходимо изменить movingAverage[i]=sum/j; для обработки корпуса, если j - 0. В частности, это должно быть movingAverage[i]=sum/averageLength;, и оно должно быть применено к слоту movingAverage[i] вне цикла усреднения.

3

Поскольку это выглядит как задание, я дам вам подсказку.

Скользящее среднее имеет окно. В этом случае ширина окна равна averageLength. Это количество очков, в которых вы в среднем превышаете.

Вам нужно будет использовать averageLength как-то в петлях, которые создают скользящую среднюю. Вы не сейчас.

1

Ваш внутренний for выполняет итерирование всего массива, поэтому вы всегда получаете одинаковое среднее значение (одно для всего массива), вы должны перебирать от 0 до текущего числа внешних for.

Ваше скользящее среднее значение обновляется на основе j вашего внутреннего for; это означает, что он будет переопределять предыдущие значения в каждом новом цикле, это должно быть внутри внешнего for вместо внутреннего, используя i в качестве индекса.

Вы делите sum/j для вычисления средних, каждый новый внутренний цикл j вы разделите 0 первый sum. Я считаю, что вы имели в виду использовать j+1 вместо индекса не то же самое, как current length

Советы для устранения неполадок:

Избегайте использования переменных массивов цикла, вы должны использовать вместо array.length.

Для материи воспроизвести проблему вы могли бы дать нам изолированную проблему вместо текущего кода ... то есть:

double[] data = new double[] { 1, 5, 8 }; //your real inputs. 
double[] movingAverage = new double[data.length]; 
for (int i = 0; i < data.length; i++) { 
    double sum = 0.0; 
    for (int j = 0; j <= i; j++) { 
    ... 
    } 
} 

Представьте, если ошибка в ваших входах, как мы могли верить вам на самом деле использовали их?

0

В следующий раз, прежде чем публиковать его, воздержитесь от комментариев. Но так как вы выглядите довольно привлекательно, подумайте о том, как вы будете проходить через данные и сделайте это. Вы должны попытаться убедиться, что каждый цикл останавливается в правильной точке, и помните, что если вы остановитесь, когда больше нет чисел (например, когда вы делаете внутренний цикл, и вы можете получить только 3 числа вместо 4) программа также должна остановиться. Убедитесь, что ваш код проверяет это.

0

В скользящем среднем необходимо иметь какой-то размер окна.

Вашего размера окно averageLength, так что это будет выглядеть примерно так:

if(i <averageLength-1) 
    { 
     double sum= 0.0; 

     for(int j = 0; j < averageLength; j++) 
     { 
      sum += data[i-j]; 
     } 

     movingAverage[i]=sum/averageLength; 
    } 

для цикла начинается с текущими данными и возвращается averageLength точек данных и добавляет их. У вас будет только скользящая средняя, ​​когда у вас есть, когда у вас будет достаточно данных, а средняя будет представлять собой сумму, деленную на среднюю длину.

Примечание: не проверен только код sudo, но это идея.

0

Без каких-либо дополнительных сведений вам, вероятно, потребуется невзвешенная скользящая средняя. В любой точке A[i] во входном массиве A длины N0<=i<N) это просто среднее из предыдущих K записей массива, вплоть до A[i]. Если нет K таких значений, то в среднем значения (i+1) от A[0] до A[i] включительно.

Немного мысли покажет вам, что вам не нужно каждый раз добавлять все значения K. Просто сохраните сумму и, перейдя к следующей точке (это - «движущееся» среднее значение), вычтите значение, которое заменяется, и добавьте новое значение, которое его заменит. (В течение первых очков K-1 вы просто добавите новое значение в сумму и увеличите свой счет на 1.)

В любой момент этого процесса скользящее среднее - это текущая сумма, деленная на текущий значение счета.