Задача: Подсчет среднего значения и дисперсии числового ряда

Оцени эту статью

Эта задача имеет очень большое практическое применение: в статистической обработке данных, обработке временных рядов, в цифровой обработке сигналов применительно к цифровым отсчётам сигнала. Постановка задачи такая:

— вводится последовательность (вещественных) чисел …
— нужно просчитать, в итоге, среднее значение и дисперсию (или СКО: средне-квадратичное отклонение) числового ряда.

Напоминание для тех, кто не дружит с математикой:
— для последовательности N чисел a1, a2, … aN
— среднее значение вычисляем как M = 1 / N * SUM( i=1, N, ai )
— дисперсию вычисляем как D = 1 / N * SUM( i=1, N, ( ai — M ) ** 2 )
— СКО вычисляем как S = SQRT( D )

Фишка здесь в том, что для вычисления дисперсии прежде нужно вычислить среднее значение M. Но такое прямое вычисление потребует 2-х проходов по последовательности: сначала для вычисления M, а затем снова для вычисления D. Это непозволительная роскошь, если нужно делать вычисления для ряда в 10 000, 100 000 или 1 000 000 значений. Вычисления нужно произвести в один проход, без хранения всей последовательности: после ввода очередного числа все предыдущие теряются…

Подсказка: прежде программирования попробуйте преобразовать выражение для D так, чтобы входящее значение M вынести из-под операции суммирования.

Решение:

Прежде, чем писать код, займёмся преобразованием формулы для вычисления дисперсии (раскроем квадрат разности под суммой):

D = 1 / N * SUM( i=1, N, ( ai — M ) ** 2 ) =

= 1 / N * SUM( i=1, N, ai ** 2 ) 2 * 1 / N * SUM( i=1, N, ai ** 2 ) * M + 1 / N * N * M ** 2 =

= 1 / N * SUM( i=1, N, ai ** 2 ) — 2 * M ** 2 + M ** 2 =

= 1 / N * SUM( i=1, N, ai ** 2 ) — M ** 2

Или, если выразить это словами: усреднённая (делённая на N) сумма квадратов чисел, минус квадрат их среднего. Теперь мы можем по ходу поступления чисел ряда накапливать их сумму (s1 — для последующего вычисления среднего) и сумму квадратов (s2 — для последующего вычисления дисперсии), а вычисление итоговых характеристик отложить до завершения поступления числового ряда.

А теперь спокойно пишем реализующий это код:

Всего то! (код сильно упрощён: весь числовой ряд вводится в одной строке, заканчивающейся Enter, не включена обработка ошибочного ввода и др.).

А теперь — как это работает:

задача с решением, практика программирования на с++, Подсчет среднего значения и десперсии числового ряда

На ваши вопросы ответим в комментариях.

Рассылка новых уроков по программированию:

Olej

Об авторе Olej

Стаж практических программных разработок около 40 лет. Преподаватель международной софтверной компании Global Logic. Постоянный автор публикаций IBM Developer Works. Научный редактор книжного издательства компьютерной литературы "Символ-Плюс", Санкт-Петербург.

Добавить комментарий

Код размещайте в тегах: <pre class="lang:c++ decode:true ">YOUR CODE</pre>