Логическая ошибка вычисления среднего значения - PullRequest
0 голосов
/ 28 октября 2011

Я пытаюсь сохранить скользящее среднее внутри SharedPreference. Вот мой код:

//Get the number of captures
int numberOfCaptures = prefs.getInt(CaptureActivity.NUMBER_OF_CAPTURES, 0);
numberOfCaptures++;

//Calculate the average of all of the captures
int runningAverage = prefs.getInt(CaptureActivity.AVERAGE_BLAST_SCORE, 0);
System.out.println("Running Average: " + runningAverage);

int averageBlastScore = (runningAverage + result.getBlastScore())/numberOfCaptures;

System.out.println("Blast Score: "  + result.getBlastScore());
System.out.println("Number of Captures: " + numberOfCaptures);
System.out.println("Average Blast Score: " + averageBlastScore);

//Save it, so we can get it again if the user captures another swing
prefs.edit().putInt(CaptureActivity.AVERAGE_BLAST_SCORE, averageBlastScore).commit();
prefs.edit().putInt(CaptureActivity.NUMBER_OF_CAPTURES, numberOfCaptures).commit();

Похоже, мое среднее значение не добавляется должным образом.

Вот оно для 3 прогонов:

10-28 02:53:13.690: I/System.out(1162): Running Average: 0
10-28 02:53:13.690: I/System.out(1162): Blast Score: 96
10-28 02:53:13.690: I/System.out(1162): Number of Captures: 1
10-28 02:53:13.690: I/System.out(1162): Average Blast Score: 96

10-28 02:53:25.550: I/System.out(1162): Running Average: 96
10-28 02:53:25.550: I/System.out(1162): Blast Score: 99
10-28 02:53:25.550: I/System.out(1162): Number of Captures: 2
10-28 02:53:25.550: I/System.out(1162): Average Blast Score: 97

10-28 02:54:04.720: I/System.out(1162): Running Average: 97
10-28 02:54:04.720: I/System.out(1162): Blast Score: 100
10-28 02:54:04.720: I/System.out(1162): Number of Captures: 3
10-28 02:54:04.720: I/System.out(1162): Average Blast Score: 65

К третьему прогону у меня должно быть:

Running Average: 295
Average Blast Score: 98.3

Я не совсем уверен, что я делаю неправильно.

Ответы [ 3 ]

1 голос
/ 28 октября 2011

Посмотрите на эту строку:

int averageBlastScore = (runningAverage + result.getBlastScore())/numberOfCaptures;

Что вы ожидаете произойти после, скажем, 100-й итерации?

Вы должны найти среднее, сложив баллы и разделив наколичество захватов:

int sumBlastScore = prefs.getInt(CaptureActivity.SUM_BLAST_SCORE, 0) + result.getBlastScore();
int averageBlastScore = sumBlastScore/numberOfCaptures;

System.out.println("Running Average: " + averageBlastScore);
0 голосов
/ 28 октября 2011

Чтобы сохранить промежуточное среднее значение, вы не сохраняете действительное среднее значение, сохраняете промежуточное итоговое значение и количество выборок, а затем вычисляете среднее значение обычным способом, который составляет общее количество / выборок.Поэтому для этого набора вы должны хранить эти значения на каждом этапе.

Образцы: 96, 99, 100

Всего: 96, Образцы: 1 => AVG = 96/1 = 96

Всего: 195, Образцы: 2 => AVG = 195/2 = 97,5

Всего: 295, Образцы: 3 => AVG = 295/3 = 98,333

Неправильный способ, указанный в другом месте, состоит в том, чтобы всегда делить на два после первой выборки и просто добавлять предыдущее среднее к новой выборке.Это приведет к 99 выборкам из 100, а выборка из 0 будет иметь в среднем 50, что, очевидно, неверно.

Я бы изменил ваш код на что-то вроде

            int numberOfCaptures = prefs.getInt(CaptureActivity.NUMBER_OF_CAPTURES, 0);
            numberOfCaptures++;

            int runningTotal = prefs.getInt(CaptureActivity.RUNNING_TOTAL, 0);
            runningTotal += result.getBlastScore();

            //Calculate the average of all of the captures
            int averageBlastScore = runningTotal / numberOfCaptures;

            System.out.println("Blast Score: "  + result.getBlastScore());
            System.out.println("Number of Captures: " + numberOfCaptures);
            System.out.println("Average Blast Score: " + averageBlastScore);

            //Save it, so we can get it again if the user captures another swing
            prefs.edit().putInt(CaptureActivity.RUNNING_TOTAL, runningTotal).commit();
            prefs.edit().putInt(CaptureActivity.NUMBER_OF_CAPTURES, numberOfCaptures).commit();

Есливы настаиваете на сохранении скользящего среднего вместо промежуточного, вам нужно будет умножить это среднее на выборки ДО приращения выборок, чтобы получить предыдущий итог, а затем перейти оттуда.

0 голосов
/ 28 октября 2011

Я заметил потенциальный недостаток в вашем коде - следующая строка является виновником:

int averageBlastScore = (runningAverage + result.getBlastScore())/numberOfCaptures;

Давайте рассмотрим сценарий, в котором у вас есть 3 балла: 99,98,90

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

  • (99 + 0) / 1 = 99 ---- это нормально
  • (99+98) / 2 = 98,5 --- это нормально
  • (98,5 + 90) / 3 = 62,83 --- Вот проблема

Вместо этого после второй итерации выкаждый раз нужно делить на 2.

Еще один способ решения этой проблемы - подождать, пока вы не получите все результаты, а затем поделить общее количество на количество снимков.

...