0

我需要一个程序来计算一组数字的移动平均值(我使用了 4、9、3.14、1.59、86.0、35.2、9.98、1.00、0.01、2.2 和 3.76)。当我运行它时,它会打印出九次“17.859999999999996”。各位看官有没有看错?

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]);
        }
    }
}
4

6 回答 6

3

由于这看起来像一个作业,我会给你一个提示。

移动平均线有一个窗口。在这种情况下,窗口的宽度为averageLength。这是你平均的点数。

您需要averageLength在创建移动平均线的循环中以某种方式使用。你现在不知道。

于 2013-10-04T20:45:52.130 回答
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++) {
   ...
  }
}

想象一下,如果错误出现在您的输入中,我们怎么能相信您真的使用了它们?

于 2013-10-04T20:54:43.220 回答
0

在移动平均线中,您需要有某种窗口大小。

你的窗口大小是平均长度,所以它看起来像这样:

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

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

        movingAverage[i]=sum/averageLength;
    }

for 循环从当前数据开始,然后返回 averageLength 数据点并将它们相加。只有当你有足够的数据点并且平均值将是总和除以平均长度时,你才会有一个移动平均值。

注意:不只测试 sudo 代码,但这就是想法。

于 2013-10-04T21:05:30.053 回答
0

如果没有任何额外的细节,您可能需要一个未加权的移动平均线。在长度A[i]的输入数组中的任何点(带有),这只是数组先前条目的平均值,直到并包括。如果没有这样的值,则平均从到的值,包括在内。AN0<=i<NKA[i]K(i+1)A[0]A[i]

稍加思考就会告诉你,你不需要每次都把所有的 K 值加起来。只需保留总和,当移动到下一个点时(这“移动”平均值),减去被替换的值并添加将替换它的新值。(在第一个 K-1 点期间,您只需将新值添加到总和中并将计数器增加 1。)

在此过程中的任何时候,移动平均值都是当前总和除以当前计数值。

于 2013-10-04T21:05:34.767 回答
0

下次,在发布之前将有关作业的评论排除在问题之外。但既然你在这方面看起来很新,想想你将如何处理数据,并让它做到这一点。您应该尝试确保每个循环都在正确的点停止,并记住,如果您在没有更多数字时停止,(例如当您执行内部循环时,您只能获得 3 个数字而不是 4 个)该程序也需要停止。确保您的代码正在检查这一点。

于 2013-10-04T20:56:22.427 回答
0

您每次都在遍历所有数据。你应该有for(int j=(i>=averageLength?i-averageLength/2:0); j< i+averageLength/2 && j<numDataPoints; j++)(或类似的东西)作为你最内心的平均值。

此外,movingAverage[i]=sum/j;应该修改以处理 is 时的j情况0。特别是,它可能应该movingAverage[i]=sum/averageLength;并且应该应用于movingAverage[i]平均循环之外的插槽。

于 2013-10-04T20:42:28.690 回答