Язык Си в примерах/Максимум
- Компиляция программ
- Простейшая программа «Hello World»
- Учимся складывать
- Максимум
- Таблица умножения
- ASCII-коды символов
- Верхний регистр
- Скобочки
- Факториал
- Степень числа
- Треугольник Паскаля
- Корень уравнения
- Система счисления
- Сортировка
- Библиотека complex
- Сортировка на основе qsort
- RPN-калькулятор
- RPN-калькулятор на Bison
- Простая грамматика
- Задача «Расчёт сопротивления схемы»
- Простая реализация конечного автомата
- Использование аргументов командной строки
- Чтение и печать без использования stdio
- Декодирование звукозаписи в формате ADX
- Другие примеры
- XCC C
- Дано
- непустая последовательность разделенных пробельными символами целых чисел (в «текстовом» десятичном представлении) на стандартном вводе программы. Последовательность конечна, но ее длина заранее неизвестна.
- Найти
- предельные значения последовательности (минимум, максимум) и основные статистики (среднее, среднеквадратичное отклонение.)
- Указания
- воспользуйтесь циклом «пока» (
while
) для чтения последовательности и функциямиpow
,sqrt
для вычисления среднеквадратичного отклонения.
Решение
править
#include <assert.h>
#include <math.h>
#include <stdio.h>
int
main ()
{
int n = 1, cur, min, max;
double sum, sum_sq;
int r
= scanf ("%d", &cur);
assert (r == 1);
sum = min = max = cur;
sum_sq = pow (cur, 2);
while (1 == (r = scanf ("%d", &cur))) {
if (cur < min) {
min = cur;
} else if (cur > max) {
max = cur;
}
++n;
sum += cur;
sum_sq += pow (cur, 2);
}
assert (r == EOF);
assert (! ferror (stdin));
printf (("Range: [%d, %d]\n"
"Count: %d\n"
"Mean: %lg\n"
"StdDev: %lg\n"),
min, max, n, sum / n,
sqrt (sum_sq / n - pow (sum / n, 2)));
return 0;
}
Вычисление и вывод результатов
правитьРазбор программы вновь начнем с ее завершения — вызова функции printf
[1] для вывода результатов ее работы. В данном случае, мы выводим значения переменных min, max, n (обновляемых после успешного чтения каждого очередного элемента числовой последовательности.) Среднее значение считаем как отношение суммы всех элементов (sum) к их количеству (n).
Среднеквадратичное отклонение вычислено как корень из дисперсии, которая, в свою очередь, вычислена по правилу «среднее квадратов минус квадрат среднего» — sum_sq / n - pow (sum / n, 2)
— тривиально следующему из ее определения. Значение используемой нами здесь функции pow
— первый аргумент, возведенный в степень, заданную вторым аргументом; значение sqrt
— квадратный корень единственного аргумента. Эти функции является частью стандартной библиотеки и объявлены в заголовке math.h
.[2][3]
Чтение и накопление
правитьЧтение последовательности выполнено в два этапа. Вначале, считанный первым элемент используется для инициализации предельных значений (min, max) и сумм (sum, sum_sq).
Затем, каждый очередной элемент (все так же считываемый функцией scanf
[4]) подвергается следующей обработке:
- сравнивается с текущими значениями переменных min, max; если элемент лежит вне этих пределов — один из них изменяется соответственно;
- значение суммы (sum) увеличивается на величину текущего элемента; значение суммы квадратов (sum_sq) — на величину квадрата;
- кроме того, успешное чтение элемента приводит к инкременту (увеличению на 1) хранящей количество считанных элементов переменной n.
Каждый вызов scanf ("%d", &cur)
считывает целое число в десятичной записи (%d
) в переменную cur
. Предшествующие числу пробельные символы (пробел, табуляция, перевод строки) при этом игнорируются, а значит могут быть использованы — в любых сочетаниях — для разделения элементов последовательности.
Условия корректности ввода
правитьПосле завершения чтения последовательности, мы требуем (используя уже известную нам макроподстановку assert
[5]) истинности следующих двух условий, смысл которых сводится к тому, что чтение последовательности не было прервано ни появлением во входном потоке каких-либо «нечисловых» данных, ни ошибкой ввода-вывода.
- Мы проверяем равенство последнего возвращенного функцией
scanf
значения константе (макроопределению)EOF
(конец файла; англ. end of file), что соответствует или исчерпанию нашего входного потока (стандартного ввода), или возникновению ошибки ввода-вывода. Другое возможное на данном этапе значение — ноль — укажет на наличие во входном потоке данных, которые не были опознаны функциейscanf
как требуемое условием целое число в десятичной записи (%d
). - Если предыдущее требование выполняется (иными словами — останов произошел не из-за «нечислового» ввода), мы также явно требуем ложности значения функции признака ошибки
ferror
для стандартного ввода (stdin
.)[6]
Цикл «пока»
править
При чтении элементов последовательности начиная со второго мы используем оператор цикла «пока» while
, синтаксис которого напоминает синтаксис рассмотренного ранее условного оператора контекста утверждения if
:[7]
while (выражение)
тело
Подобно оператору if
, если результат вычисления выражения — ложь (другими словами — 0), тело не выполняется и реализация языка Си просто переходит к следующему утверждению (англ. statement) кода.
Если же результат — истина (отличен от 0), выполняется тело, после чего реализация вновь возвращается к началу цикла.
В нашем случае, условием продолжения выполнения цикла является равенство единице количества успешно считанных scanf
значений. Тем самым, цикл можно прочитать следующим образом:
- пока удается считать очередное значение?
- обновляй переменные min, max, n, sum, sum_sq.
Задания
править- Измените программу для вычисления предельных значений и статистик последовательности чисел с плавающей запятой.
- В условии задачи мы потребовали наличия в последовательности хотя бы одного элемента. Определите, какие сложности возникнут при попытке обобщить данную программу на случай пустой последовательности?
- Дополните программу выводом «промежуточных» значений — суммы элементов последовательности и суммы их квадратов.
- Реализуйте также вычисление и вывод моментов случайной величины вплоть до четвертого и, на их основе, — коэффициента асимметрии и коэффициента эксцесса.
См. также
правитьПримечания
править- ↑ 7.21.6.1 The fprintf function(англ.) WG14 N1570 Committee Draft. ISO/IEC (2011-04-12). Проверено 2012-11-19 г.
- ↑ 7.12.7.4 The pow functions(англ.) WG14 N1570 Committee Draft. ISO/IEC (2011-04-12). Проверено 2012-11-19 г.
- ↑ 7.12.7.5 The sqrt functions(англ.) WG14 N1570 Committee Draft. ISO/IEC (2011-04-12). Проверено 2012-11-19 г.
- ↑ 7.21.6.2 The fscanf function(англ.) WG14 N1570 Committee Draft. ISO/IEC (2011-04-12). Проверено 2012-11-19 г.
- ↑ 7.2.1.1 The assert macro(англ.) WG14 N1570 Committee Draft. ISO/IEC (2011-04-12). Проверено 2012-11-19 г.
- ↑ 7.21.10.3 The ferror function(англ.) WG14 N1570 Committee Draft. ISO/IEC (2011-04-12). Проверено 2012-11-19 г.
- ↑ 6.8.5.1 The while statement(англ.) WG14 N1570 Committee Draft. ISO/IEC (2011-04-12). Проверено 2012-11-19 г.