|
Программирование >> Структурное программирование
Типичная ошибка программирования 2.9 Использование чисел с плавающей запятой в предположении, что они совершенно точные, может приводить к некорректным результатам. Числа с плавающей запятой на большинстве компьютеров являются приближенными. Хороший стиль программирования 2.9 Не следует сравнивать числа с плавающей запятой на их равенство или неравенство друг другу. Лучше проверять, не меньше ли их разность некоторой заданной малой величины. налево и тот же приоритет, что и у унарных операций унарный + и унарный -. Это тот же приоритет, что у мультипликативных операций *, / и %, и он на один уровень ниже, чем у скобок. Мы укажем операцию приведения к типу в нотации (тип) в таблице приоритетов. Возможности форматирования, использованные в программе рис. 2.9, подробно будут изучены в главе 11, а пока ограничимся их кратким обсуждением. Обращение setprecision(2) в операторе вывода cout << Среднее значение равно << setprecision(2) setiosflags(ios::fixed ios::showpoint) average endl; указывает, что переменная average типа float должна быть напечатана с точностью до двух разрядов после десятичной точки (т.е. 92.37). Это обращение является параметризованным манипулятором потока. Программы, использующие подобные обращения, должны содержать директиву #include <iomanip.h> Отметим, что endl является непараметризованным манипулятором потока и не требует заголовочного файла iomanip.h. Если точность не задана, то число с плавающей запятой выводится с точностью в шесть разрядов (т.е. с точностью по умолчанию), хотя мы сразу же увидим исключение из этого правила. Манипулятор потока setiosflags(ios::fixed ios::showpoint) в приведенном выше операторе задает две опции выходного формата, а именно - ios::fixed и ios::showpoint. Символ вертикальной черты () разделяет множество опций в обращении setiosflags (мы более подробно объясним нотацию в главе 6). Опция ios::fixed приводит к выводу числа с плавающей запятой в так называемом формате с фиксированной точкой (в отличие от научной нотации, которая будет обсуждаться в главе 11). Опция ios::showpoint приводит к выводу десятичной точки и нулевых младших разрядов даже если величина в действительности является целым числом, например, 88.00. Без опции ios::showpoint подобная величина была бы напечатана как 88, т.е. без нулевых младших разрядов и без десятичной точки. Когда приведенный выше формат используется в программе, печатаемая величина округляется до указанного числа десятичных разрядов, хотя ее значение в памяти остается неизменным. Например, числа 87.945 и 67.543 будут напечатаны соответственно в виде 87.95 и 67.54. Несмотря на то, что числа с плавающей запятой не всегда стопроцентно точные , они широко используются на практике. Например, когда мы говорим, что нормальная температура тела 98.6, нас не интересует значение температуры с большим числом разрядов. Когда мы смотрим на термометр и видим, что он показывает температуру 98.6, в действительности она может быть равна 98.5999473210643. Однако, для большинства приложений достаточно считать, что эта температура равна 98.6. Числа с плавающей запятой могут получаться также в результате деления. Когда мы делим 10 на 3, результат равен 3.3333333... с бесконечно повторяемой периодической частью 3. Компьютер располагает только фиксированным объемом памяти для хранения подобных величин, так что, естественно, сохраняемое значение будет только приближенным. 2.10. Нисходящая разработка алгоритмов с пошаговой детализацией: учебный пример 3 (вложенные управляющие структуры) Давайте теперь поработаем над другой задачей. Мы снова будем разрабатывать алгоритм, используя псевдокод, нисходящее проектирование и пошаговую детализацию для создания программы на С++. Мы уже видели, что управляющие структуры могут собираться в пакеты, одна за другой (последовательно), как ребенок собирает кубики. А в данном учебном примере мы увидим другой путь соединения управляющих структур в С++ - вложенные структуры. Рассмотрим следующую постановку задачи: Колледж предлагает курс, который готовит студентов для государственного экзамена на получения лицензии брокера. В прошлом году несколько студентов, прослушавших этот курс, сдавали такой экзамен. Естественно, колледж хочет знать, насколько хорошо их студенты его сдали. Вас попросили написать программу обработки результатов экзамена. Вам дали список 10-и студентов. После каждой фамилии записано 1, если студент успешно сдал экзамен, и 2, если он его не смог сдать. Ваша программа должна проанализировать результаты экзамена следующим образом: 1. Ввести каждый результат тестирования (т.е. 1 или 2). Перед вводом каждого результата программа должна выводить на экран приглашение Введите результат . 2. Подсчитать число результатов каждого типа. 3. Вывести на экран суммарный результат, указав число студентов, выдержавших и не выдержавших экзамен. 4. Если более 8 студентов экзамен выдержали, напечатать сообщение Повысить плату за обучение . Прочтя внимательно формулировку задания на решение данной задачи, вы можете отметить следующее: 1. Программа должна обработать 10 результатов тестирования. Можно будет использовать повторение, управляемое счетчиком. 2. Каждый результат тестирования - число, равное или 1, или 2. При каждом чтении очередного результата программа должна определять, равно ли введенное число 1, или 2. Мы будем в нашем алгоритме проверять, не равно ли число 1. Если число не 1, то мы будем предполагать, что оно равно 2. (Упражнение в конце главы рассмотрит последствия этого предположения.) 3. Надо использовать два счетчика - один для подсчета числа студентов, сдавших экзамен, и второй для подсчета числа студентов, не выдержавших испытание. 4. После того, как программа обработает все результаты, она должна решить, больше ли 8-и студентов успешно сдали экзамен. Давайте проведем нисходящую разработку с пошаговой детализацией. Мы начнем с псевдокода, описывающего самый верхний уровень: Проанализировать результаты экзамена и решить, должна ли быть повышена плата за обучение Снова подчеркнем, что самый верхний уровень описывает программу в целом, но обычно необходимо пройти через ряд детализаций, прежде чем псевдокод можно будет естественным образом преобразовать в программу на С++. Наша первая детализация: Задать начальные значения переменных Ввести десять оценок и посчитать число сдавших и не сдавших экзамен Напечатать суммарные результаты экзамена и решить, надо ли повышать плату за обучение Мы полностью описали всю программу, но, конечно, необходимы дальнейшие детализации. Определим необходимые нам переменные. Нам нужны счетчики для записи числа сдавших (passes) и не сдавших (failures) экзамен, счетчик для управления циклом (student) и переменная для хранения введенной оценки (result). Поэтому предложение псевдокода Задать начальные значения переменных можно детализировать следующим образом: Задать начальное значение О переменной passes Задать начальное значение О переменной failures Задать начальное значение О переменной student Отметим, что инициируются только счетчики. Предложение псевдокода Ввести десять оценок и посчитать число сдавших и не сдавших экзамен требует цикла для ввода результата каждого экзамена. В данном случае заранее известно, что число вводимых результатов ровно десять, так что можно использовать повторение, управляемое счетчиком. Внутри цикла потребуется структура (вложенная) двойного выбора, которая будет определять для каждой введенной оценки ее тип и увеличивать на единицу соответствующий счетчик. Таким образом, детализация приведенного предложения псевдокода имеет вид: ПОКА счетчик student меньше или равен десяти Ввести очередную оценку экзамена
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |