Язык Си в примерах/Максимум: различия между версиями
Содержимое удалено Содержимое добавлено
ISbot (обсуждение | вклад) м {{BookCat}}; избыточные <big /> и <font /> вокруг <source />; ссылки; пробелы. |
Переписано. |
||
Строка 1:
{{{{Book template}}/Содержание
; {{Якорь2 |Дано}}: непустая последовательность разделенных ''пробельными символами'' [[w:Целое число |целых чисел]] (в «текстовом» представлении) на [[w:Стандартные потоки#Стандартный ввод |стандартном вводе]] программы. Последовательность конечна, но ее длина заранее неизвестна.
; Найти: предельные значения последовательности (минимум, максимум) и основные статистики (среднее, среднеквадратичное отклонение.)
== Решение ==
{{Якорь |intstats.c}}
<source lang="c">
#include <assert.h>
#include <stdio.h>
int
main ()
{
int n = 1, cur, min, max;
double sum = 0, sum_sq = 0;
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);
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;
}
</source>
Разбор программы вновь начнем с ее завершения — вызова функции <code >printf</code><ref name="fprintf" /> для вывода результатов ее работы. В данном случае, мы выводим значения переменных <var >min</var>, <var >max</var>, <var >n</var> (обновляемых после успешного чтения каждого очередного элемента числовой последовательности.) Среднее значение считаем как отношение ''суммы'' всех элементов (<var >sum</var>) к их ''количеству'' (<var >n</var>).
''Среднеквадратичное отклонение'' вычислено как корень из [[w:Дисперсия |дисперсии]], которая, в свою очередь, вычислена по правилу «среднее квадратов минус квадрат среднего» — <source lang="c" enclose="none" >sum_sq / n - pow (sum / n, 2)</source> — тривиально следующему из ее определения. Значение используемой нами здесь функции <code >pow</code> — первый аргумент, возведенный в степень, заданную вторым аргументом; значение <code >sqrt</code> — квадратный корень единственного аргумента. Эти функции является частью ''стандартной библиотеки'' и ''объявлены'' в ''заголовке'' <code >math.h</code>.<ref name="pow" /><ref name="sqrt" />
Чтение последовательности выполнено в два этапа. Вначале, считанный первым элемент используется для инициализации ''предельных значений'' (<var >min</var>, <var >max</var>) и ''сумм'' (<var >sum</var>, <var >sum_sq</var>).
Затем, каждый очередной элемент (все так же считываемый функцией <code >scanf</code><ref name="fscanf" />) подвергается следующей обработке:
# сравнивается с текущими значениями переменных <var >min</var>, <var >max</var>; переменные обновляются соответственно;
# значение ''суммы'' (<var >sum</var>) увеличивается на величину текущего элемента; значение ''суммы квадратов'' (<var >sum_sq</var>) — на величину квадрата;
# кроме того, успешное чтение элемента приводит к ''инкременту'' (увеличению на 1) хранящей количество считанных элементов переменной <var >n</var>.
Каждый вызов <source lang="c" enclose="none" >scanf ("%d", &cur)</source> считывает целое десятичное число в десятичной записи (<code >%d</code>) в переменную <code >cur</code>. <em >Предшествующие</em> числу ''пробельные символы'' (пробел, табуляция, [[w:Перевод строки |перевод строки]]) при этом игнорируются, а значит могут быть использованы — в любых сочетаниях — для ''разделения'' элементов последовательности.
{{Якорь |while}}
При чтении элементов последовательности начиная со второго мы используем оператор цикла «пока» <code >while</code>, ''синтаксис'' которого напоминает синтаксис [[../Учимся складывать#if |рассмотренного ранее]] ''условного оператора контекста утверждения'' <code >if</code>:<ref name="while" />
<code >while (<var class="angled" >выражение</var>)
<var class="angled" >тело</var></code>
Подобно оператору <code >if</code>, если результат вычисления <var >выражения</var> — ложь (другими словами — 0), <var class="angled" >тело</var> не выполняется и ''реализация'' языка Си просто переходит к следующему ''утверждению'' (англ. {{lang |en|statement}}) кода.
Если же результат — истина (отличен от 0), выполняется <var class="angled" >тело</var>, после чего реализация <em >вновь возвращается</em> к началу цикла.
В нашем случае, ''условием продолжения'' выполнения цикла является равенство единице количества успешно считанных <code >scanf</code> значений. Тем самым, цикл можно прочитать следующим образом:
: ''пока'' удается считать очередное значение?
:: обновляй переменные <var >min</var>, <var >max</var>, <var >n</var>, <var >sum</var>, <var >sum_sq</var>.
После завершения чтения последовательности, мы ''требуем'' (используя [[../Учимся складывать#assert |уже известную]] нам макроподстановку <code >assert</code><ref name="assert" />) равенства последнего возвращенного функцией <code >scanf</code> значения константе (макроопределению) <code >EOF</code> — что соответствует достижению ''конца файла'' для ''стандартного ввода''. Иными словами, чтение последовательности не должно быть прервано наличием во входном потоке «нечисловых» данных.
== Задания ==
# Измените [[#intstats.c |программу]] для вычисления предельных значений и статистик последовательности [[w:Число с плавающей запятой |чисел с плавающей запятой.]]
# В [[#Дано |условии задачи]] мы потребовали наличия в последовательности хотя бы одного элемента. Определите, какие сложности возникнут при попытке обобщить данную программу на случай ''пустой'' последовательности?
# Дополните программу выводом «промежуточных» значений — суммы элементов последовательности и суммы их квадратов.
# Реализуйте также вычисление и вывод [[w:Моменты случайной величины |моментов случайной величины]] вплоть до четвертого и, на их основе, — [[w:Коэффициент асимметрии |коэффициента асимметрии]] и [[w:Коэффициент эксцесса |коэффициента эксцесса]].
== См. также ==
* {{w |Математическое ожидание}}
* {{w |Среднеквадратическое отклонение}}
== Примечания ==
{{Примечания | refs =
<!-- Пожалуйста поддерживайте алфавитный порядок для name. Спасибо. -->
<ref name="assert" >{{Cite web | title = 7.2.1.1 The assert macro | url = http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf#page=204 | work = WG14 N1570 Committee Draft | publisher = ISO/IEC | datepublished = 2011-04-12 | lang = en | accessdate = 2012-11-19}}</ref>
<ref name="fprintf" >{{Cite web | title = 7.21.6.1 The fprintf function | url = http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf#page=327 | work = WG14 N1570 Committee Draft | publisher = ISO/IEC | datepublished = 2011-04-12 | lang = en | accessdate = 2012-11-19}}</ref>
<ref name="fscanf" >{{Cite web | title = 7.21.6.2 The fscanf function | url = http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf#page=335 | work = WG14 N1570 Committee Draft | publisher = ISO/IEC | datepublished = 2011-04-12 | lang = en | accessdate = 2012-11-19}}</ref>
<ref name="pow" >{{Cite web | title = 7.12.7.4 The pow functions | url = http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf#page=266 | work = WG14 N1570 Committee Draft | publisher = ISO/IEC | datepublished = 2011-04-12 | lang = en | accessdate = 2012-11-19}}</ref>
<ref name="sqrt" >{{Cite web | title = 7.12.7.5 The sqrt functions | url = http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf#page=267 | work = WG14 N1570 Committee Draft | publisher = ISO/IEC | datepublished = 2011-04-12 | lang = en | accessdate = 2012-11-19}}</ref>
<ref name="while" >{{Cite web | title = 6.8.5.1 The while statement | url = http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf#page=169 | work = WG14 N1570 Committee Draft | publisher = ISO/IEC | datepublished = 2011-04-12 | lang = en | accessdate = 2012-11-19}}</ref>
}}
{{BookCat}}
|