КАТЕГОРИИ: Архитектура-(3434)Астрономия-(809)Биология-(7483)Биотехнологии-(1457)Военное дело-(14632)Высокие технологии-(1363)География-(913)Геология-(1438)Государство-(451)Демография-(1065)Дом-(47672)Журналистика и СМИ-(912)Изобретательство-(14524)Иностранные языки-(4268)Информатика-(17799)Искусство-(1338)История-(13644)Компьютеры-(11121)Косметика-(55)Кулинария-(373)Культура-(8427)Лингвистика-(374)Литература-(1642)Маркетинг-(23702)Математика-(16968)Машиностроение-(1700)Медицина-(12668)Менеджмент-(24684)Механика-(15423)Науковедение-(506)Образование-(11852)Охрана труда-(3308)Педагогика-(5571)Полиграфия-(1312)Политика-(7869)Право-(5454)Приборостроение-(1369)Программирование-(2801)Производство-(97182)Промышленность-(8706)Психология-(18388)Религия-(3217)Связь-(10668)Сельское хозяйство-(299)Социология-(6455)Спорт-(42831)Строительство-(4793)Торговля-(5050)Транспорт-(2929)Туризм-(1568)Физика-(3942)Философия-(17015)Финансы-(26596)Химия-(22929)Экология-(12095)Экономика-(9961)Электроника-(8441)Электротехника-(4623)Энергетика-(12629)Юриспруденция-(1492)Ядерная техника-(1748) |
Расчетная Работа
End. Repeat Begin s:= s - mk; mk:= 0; k:= k+1; end; until k > n-1; End; В данном случае отмеченная группа операторов повторяется дважды. Такое явление типично для программ, подвергнутых «насильственной» структуризации. То есть изначально неструктурный алгоритм видоизменяют, приспосабливая под требования структурного программирования. Чтобы избежать подобных нонсенсов, необходимо с самого начала, при разработке алгоритма мыслить структурно.
Контрольные вопросы и задания
1. Написать структурный вариант алгоритма генерации чисел mi (пример 2.2). За основу рекомендуется взять следующую идею. Пусть (k1, k2, …,kn-1) – некоторое сочетание (n-1) элементов из d возможных. Тогда числа mi и ki связаны следующим соотношением: mi = ki –ki-1, i=1,…,n-1; k0=0; (1) mn = d – kn-1. Алгоритм генерации сочетаний можно найти в [6]. 2. Написать структурный вариант программы бинарного метода возведения целую неотрицательную степень m произвольного вещественного числа x. За основу взять следующий неструктурный алгоритм [4, т.2]: Шаг 1. Начальная установка: N:= m; Y:= 1; Z:= x. Шаг 2. Установить N:= [N/2] и одновременно определить, было ли старое значение N четно или нечетно. Если N было четно, перейти к шагу 5. Шаг 3. Установить: Y:=Y * Z. Шаг 4. Если N=0, то алгоритм закончен, ответ равен Y. Шаг 5. Установить Z:= Z * Z. Вернуться к шагу 2. 3. Доказать соотношение (1). 4. Для следующих вариантов заданий составить программу, устойчивую к модификации. При проектировании логики модуля использовать пошаговую детализацию, записать все промежуточные шаги. Варианты заданий 1) Дан однонаправленный список L1. Включить в него перед вторым вхождением элемента с заданным значением E подсписок L2. 2) Дан однонаправленный список L1. Включить в него перед предпоследним вхождением элемента с заданным значением E подсписок L2. 3) Дан однонаправленный список L, элементы которого отсортированы по невозрастанию. Вставить в список k новых элементов, удаляя каждый раз последний элемент, чтобы упорядоченность сохранялась. 4) Дан однонаправленный список L1. Определить, есть ли в нем подряд идущие элементы, составляющие список L2. 5) Дан однонаправленный список L из элементов целого типа. Из каждой группы подряд идущих равных элементов оставить в списке только один. 6) Даны однонаправленные списки L1 и L2. Сформировать список L=L1 L2. 7) Даны однонаправленные списки L1 и L2. Сформировать список L=L1 L2. 8) Дан однонаправленный список L из элементов целого типа. Если в нем три подряд идущих элемента образуют строго возрастающую последовательность – исключить средний элемент. 9) Дан однонаправленный список L. Включить в него k новых элементов, вставляя их на заданные места в списке, одновременно удаляя другие заданные элементы. Места включаемого и удаляемого элемента не должны совпадать. 10) Дан однонаправленный список L. Пусть Li, Li+1 – два последовательных элемента списка. Получить все вещественные корни квадратного уравнения x2+Lix+Li+1=0, i=1,…,n. 11) Дан однонаправленный список L. Найти за один просмотр списка три его максимальных элемента и переместить их в начало списка в порядке убывания. 12) Дан однонаправленный список L. Если в нем три подряд идущих элемента составляют выпуклую тройку – исключить два крайних элемента всех таких троек. 13) Дан однонаправленный список L из элементов целого типа. Считая, что два первых его элемента L1 и L2 соответствуют 1-му и 2-му членам арифметической прогрессии, оставить в списке только члены этой прогрессии. 14) В однонаправленном списке L содержится n элементов (n≤12,тип элемента integer), среди которых могут быть совпадающие. Определить, сколько в списке пар одинаковых элементов, сколько троек, четверок, …, n -ок. Если в списке есть k совпадающих элементов, то при подсчете (k-1) -ок, (k-2)- ок и т.д. эти элементы не учитывать. Указание: воспользоваться алгоритмом генерации сочетаний [6].
3. Защитное программирование
Защитное программирование можно считать вторым по эффективности после предупреждения средством борьбы с ошибками ПО. Следует помнить основную идею защитного программирования: включение дополнительных операторов контроля, используя программную и временную избыточность. Считается, что защитное программирование, используемое в меру, позволяет на порядок повысить надежность ПО.
3.1 Контроль входных данных
Худшее, что может сделать модуль – принять неправильные входные данные, а затем вернуть неверный, но правдоподобный результат. Чтобы избежать подобной ситуации, в начале каждого модуля необходимо поместить операторы проверки входных данных на соответствие их свойств указанным атрибутам и диапазонам измерения. Важно по тексту выявлять все неявные предположения, которые в нем сделаны о свойствах входных данных, а затем внести проверки на соответствие реальных данных этим предположениям. Рекомендуются следующие проверки: 1. Проверка на предполагаемый тип и диапазон измерения. Не во всех языках программирования философия строгого соответствия типов выдерживается, потому проверка совпадения типов не будет лишней. Необходимо также следить, чтобы проверка на диапазон была исчерпывающей. Например, если ожидаемое значение целочисленной переменной k может быть 1, 2 или 3, то из того, что k≠1 и k≠2 не следует, что k=3. 2. Проверка граничных значений данных. Особое внимание необходимо уделить «нулевому варианту», когда от программы требуется «ничего не делать» – типа вычисления 0! или создания набора элементов нулевой длины. 3. Проверка на корректность данных – реакция программы должна быть адекватной (см. раздел 1 – реакция устойчивой программы на некорректные данные).
3.2 Контроль промежуточных данных
Иногда бывает сложно определить границы входных данных, при которых решение не существует. В этом случае корректность данных приходиться выявлять в процессе их обработки. Возможна также ситуация, когда входные данные корректны и решение существует, но промежуточные данные выходят за допустимый диапазон. Например, при использовании метода квадратного корня для решения системы линейных уравнений с действительными коэффициентами промежуточные результаты могут быть комплексными. В таком случае, в зависимости от промежуточных данных, необходимо использовать разные варианты алгоритма, но для этого также нужен контроль промежуточных данных. Типичными можно считать следующие случаи некорректности промежуточных данных. 1. Недопустимые значения аргументов функций (логарифм, квадратный корень). Можно отметить случай вычисления е-х при большом значении х. Вместо того, чтобы положить результат, равный машинному нулю, выдается сигнал переполнения. Для борьбы с такой ситуацией необходимо определить допустимый диапазон значения аргумента и перед вычислением функции проверять значение аргумента на допустимость. 2. Выход значений индексов массива за границы, указанные при объявлении. Это может произойти, когда значения индексов вычисляются по какому-либо алгоритму. При подобной ситуации используются данные из ячеек, расположенных рядом с массивом. Реакция программы может быть самой экзотичной, с первого взгляда противоречащей здравому смыслу. Во избежание такого стресса, после вычисления значений индексов надо проверять их на принадлежность объявленному диапазону. 3. Переполнение. Наиболее коварно целочисленное переполнение. В языке Pascal максимальное значение целого числа (системная константа MaxInt) равно 215 – 1=32767. Как правило ситуация целочисленного переполнения не диагностируется системой, а происходит циклическое урезание результата, то есть из ответа вычитается 65536=216. Таким образом при выполнении сложения 25000+10000 ответ будет 350000 – 65536= – 30536. Поэтому необходима проверка: if a<MaxInt – b then c:= a+b; Неправильно: if a + b < MaxInt then c:= a+b; При опасности вещественночисленного переполнения рекомендуется использовать нормировочные коэффициенты. Например, надо решить квадратное уравнение 1012х2+5·1018х+4·1024=0. Решение существует: х1= – 106, х2= – 4·106, но при вычислении дискриминанта D=b2 – 4ac получим b2=25·1036 – будет переполнение. Данное уравнение можно привести к виду x2+px+q=0, поделив на а=1012. Общая рекомендация: всегда полезно привести формулы к безразмерному виду. 4. Потеря точности. Задача: вычислить с точностью 10– 8 значение При больших х вычислительная погрешность будет очень велика, может быть более 100%. Это происходит потому, что при больших х ряд сходится медленно, слагаемые имеют разные знаки и близки по модулю. Такая ситуация является главным источником вычислительной погрешности. Например, 47.132–47.111=0.021, где уменьшаемое и вычитаемое известны с точностью до 5 значащих цифр, то есть их относительная погрешность . У разности известны 2 значащие цифры, то есть относительная погрешность равна . В такой ситуации рекомендуется изменить вычисляемую формулу. Например, положить . В этом варианте все слагаемые положительны, погрешности не будет. Пример 3.1. Вычислить . Если вычислять с точностью до 8 значащих цифр, то получим U=3.54·10-5. Для получения большей точности ответа можно преобразовать формулу: , все знаки верные. При вычислениях всегда полезно знать предельную точность, которая достигается в данной системе программирования. Это можно определить с помощью следующей программы: Var p,d,e:real; Begin readln(d); e:= 1; e:= e/2; p:= d + e; until p=d; writeln (2*e); Здесь d – какое-либо число, относительно которого надо определить точность, например d=1. Переменная e делится на 2 потому, что деление на 2 происходит без потери точности. 5. Переполнение динамической памяти. При выполнении некоторых алгоритмов, использующих динамическую память, получается много промежуточных результатов. Если не производить своевременную выгрузку, то очень быстро наступает переполнение динамической памяти. Выгрузку следует проводить сразу после использования промежуточного данного. Для контроля возможного переполнения в языке Pascal, например, есть специальные функции SizeOf(x) – объем памяти, требующийся под переменную х и MaxAvail – максимальный размер свободной области динамической памяти. Проверка выглядит так: If SizeOf(x) < MaxAvail then new(p); Здесь p – указатель переменной х. 6. Неправильное использование локальных и глобальных переменных. Очень распространенная ситуация, при которой в процедуре под промежуточные данные (например, параметр цикла) используются глобальные переменные. В этом случае порча результата почти неизбежна. Рекомендуется не употреблять глобальные переменные без крайней необходимости, когда они должны быть доступны одновременно нескольким процедурам. Все промежуточные переменные должны быть локальными. Итак, защитное программирование является мощным средством борьбы с ошибками кодирования и проектирования. Следует, однако, помнить, что употреблять его следует в меру. Для этого надо: 1) изучить по логике модуля все предположения о входных данных и составить список всех возможных проверок; 2) оценить: - сложность каждой проверки; - вероятность того, что данные будут содержать ошибку; - последствия отсутствия проверки. 3) выработать необходимый минимум защиты. 4. Практические рекомендации по надежному программированию 4.1 О структурном программировании
1. Еще только приступая к проектированию логики, старайтесь мыслить в терминах структурного программирования. 2. Избегайте операторов goto всюду где возможно, но не ценой ясности программы. Оператор goto хорошо применять: - для аварийного выхода из цикла; - для перехода к концу программы; - во избежании слишком большой глубины вложенности ветвления.
4.2 Работа с данными
1. Явно объявляйте все переменные и все их атрибуты, не пользуйтесь умолчанием. В некоторых компиляторах выбор по умолчанию можно перенастраивать, не зная о текущей настройке, можно нарваться на неприятности. 2. Избегайте явных констант, кроме 0 и 1. 3. Не используйте переменную более чем для одной цели. Исключения могут составлять переменные для цикла. 4. Не используйте особое значение переменных с особым смыслом. Пример 4.1. Переменная ДлСтроки равна числу символов в строке А, если же ДлСтроки=0, то так сообщается об ошибке ввода, то есть особое значение 0 используется не по назначению. 5. Будьте осторожны с двоичной машиной. Пример 4.2. Если А=0.1 и В=0.6, то if A*B=0.06 then … может никогда не сработать, так как 0.1 и 0.6 не переводятся точно в двоичную систему. 4.3 Правила хорошего тона составления структуры программы
1. Предусмотрите else для каждого then (if). Если ничего не надо делать по этому else, то поставьте пустой оператор, либо не используйте else вообще. 2. Выполняйте исчерпывающие проверки. 3. Как можно реже используйте внутренние процедуры. 4. По возможности чаще используйте рекурсию, так как алгоритм перебора с возвратом – очень распространенное явление. 5. Используйте свободу синтаксиса языка для придания программе лучшей читабельности: - физически отделяйте блоки; - используйте дополнительные пробелы для выделения частей операторов; - пишите лесенкой, не скупясь на отступы; - используйте большие буквы и знаки подчеркивания для придания большей выразительности именам.
4.4 Комментарии
1. Лучшей документацией внутренней логики является простая и ясная структура текста программы. Обилие комментариев нежелательно, так как человек, отлаживающий программу, склонен им верить. 2. В начале модуля пишите его внешнюю спецификацию. Можно прокомментировать каждый законченный фрагмент и каждое ветвление. 3. Комментарии не должны дублировать текст оператора. Комментируйте текст так, как будто отвечаете на вопросы читателя. 4. Физически выдвигайте комментарий из текста собственно программы.
4.5 Микроэффективность
Микроэффективность – повышение эффективности программы за счет тривиальных приемов, как то – отказ от индексирования, замены возведения в степень на многократное умножение и т.д. 1. Игнорируйте все предложения по повышению эффективности пока программа не будет правильной. Если программа хорошо спроектирована, то ее легко модифицировать для повышения эффективности. 2. Не жертвуйте легкостью чтения ради эффективности. 3. Не добивайтесь эффективности ради эффективности. 4. Добивайтесь эффективности на основе измерения, а не догадки. Доказано, что программисты очень плохо угадывают причины медленной работы программы. Только после того, как программа заработает и только если она работает не эффективно, необходимо выполнить соответствующие замеры и обнаружить пресловутые 5%, которые занимают 90% времени.
5. Тестирование модулей 5.1 Идеология тестирования
Тестирование – главный способ обнаружения ошибки в действующей программе, на нем основаны также все математические модели надежности ПО. Следует помнить, что тестирование – процесс выполнения программы с целью найти в ней ошибку. То есть по определению тестирование – процесс разрушительный, тестирующий должен быть доволен, если ему удается заставить программу ошибиться. Поэтому при тестировании важен психологический настрой на доказательство ошибочности программы. В противном случае будет подсознательно блокироваться мысль о выборе особо коварного теста. В отличии от тестирования, отладка – это установление точной природы обнаруженной ошибки и ее исправление, иными словами, отладка – это то, что делают после тестирования. Тестирование модулей (автономное тестирование) – контроль отдельного программного модуля в изолированной среде. Можно выделить две главные проблемы тестирования: 1. Принципиальная невозможность проверки всех возможных ситуаций, которые могут встретиться при работе программы с реальными данными; 2. Эффект «почти правильного оператора». Рассмотрим пример: необходимо проверить условие a=b=c. Предлагается следующий оператор: if (a+b+c)/3 = a then …. Для большинства данных этот оператор будет работать правильно, ошибочная реакция возникает, если только при каком-либо h будет b=a-h, c=a+h. Единственная возможность в какой-то степени решить названные проблемы – тщательное планирование тестов.
5.2 Аксиомы тестирования
1. Невозможно тестировать собственную программу. Этому есть две причины: - вследствие того, что тестирование – процесс разрушительный, у автора программы обычно «не поднимается рука» на создание изощренного теста; - программа может содержать какую-либо ошибку из-за неправильного преобразования информации, вследствие чего очень велика вероятность, что при подготовке теста будет допущена та же ошибка. Вывод: тесты должен готовить какой-либо внешний источник. Например, при тестировании модуля тест может быть подготовлен автором вызывающего модуля. 2. Результат тестирования должен прогнозироваться до выполнения теста. Еще лучше пользоваться таким инструментом, который позволяет автоматически сверять ожидаемые и фактические результаты. 3. Избегайте невоспроизводимых тестов. Часто в режиме диалога, сидя за терминалом, программист задает тестовые входные данные «с лету», чтобы просто посмотреть «что получится». Из-за такой неряшливости тесты всякий раз приходится придумывать заново. Мораль: тестирование и без того – дорогое удовольствие, поэтому никогда не используйте тесты, которые тут же выбрасываются, если только вы не хотите следом выбросить и программу. 4. Готовьте тесты как для правильных, так и для неправильных данных. 5. По мере того, как увеличивается число обнаруженных ошибок, растет вероятность того, что в программе существуют еще ошибки. Поэтому чем больше ошибок найдено, тем тщательнее надо искать новые. 6. Не изменяйте программу, чтобы облегчить тестирование. Например, цикл должен выполниться 100 раз. Программист меняет его, чтобы цикл повторился только 10 раз. Может быть программист и занимается тестированием, но только другой программы. 7. Тестирование, как любой вид творческой деятельности, должно быть тщательно спланировано. На каждом этапе тестирования должны быть поставлены определенные задачи и выработаны способы их решения.
5.3 Методы тестирования
В качестве одного из важнейших способов тестирования следует рассматривать тестирование компиляцией. При этом обнаруживается большинство синтаксических и часть семантических ошибок. Методы тестирования откомпилированной программы можно разбить на две группы: структурное и функциональное тестирование. Структурное тестирование заключается в разработке групп тестов, которые в той или иной степени позволяют проверить прохождение различных маршрутов обработки данных. Функциональное тестирование – это разработка тестов, обеспечивающих проверку правильности выполнения функций программы. Рассмотрим эти методы подробнее. Структурное тестирование. Структурные тесты разрабатываются на основе анализа структуры программы, то есть используется принцип «белого ящика». Существуют следующие наборы требований, выполнение которых позволяет обеспечить определенный уровень полноты тестирования. 1) Покрытие всех условных блоков. Согласно этому требованию набор тестов должен быть таким, чтобы каждый блок проверки некоторого условия прорабатывал дважды: когда проверяемое условие истинно и когда ложно. 2) Покрытие всех элементарных условий. Набор тестов должен обеспечивать выполнение каждого элементарного условия в условном блоке не менее двух раз – истина и ложь. Пример 5.1. Имеем условный оператор if (x > 1) and (y = 0) then… Требованию 1) удовлетворяет два теста: (х=2, у=0) и (х=2, у=5). Требованию 2) удовлетворяют четыре теста: (х=2, у=0), (х=2, у=5), (х=0, у=0), (х=0, у=5). 3) Покрытие блоков и условий. Эти тесты должны одновременно удовлетворять требованиям 1) и 2). Функциональное тестирование. Функциональные тесты составляются на основе анализа внешних функций модуля, используя принцип «черного ящика», так как структура программы не исследуется. Применяются два метода функционального тестирования. 1) Метод эквивалентных разбиений. В области возможных значений входных данных выделяют подобласти, включающие допустимые и недопустимые значения. После этого разрабатываются тесты, покрывающие все возможные подобласти. Например, целочисленная переменная М должна принадлежать отрезку [1,12]. Следовательно, существуют три класса эквивалентности: М<1; 1≤M≤12; M>12. 2) Метод анализа граничных значений. Составляются тесты, включающие данные, значения которых соответствуют граничным значениям классов эквивалентности и ближайшие к ним. В соответствие с указанными методами для переменной М могут быть использованы следующие тестовые значения: -5, 0, 1, 2, 6, 11, 12, 13, 20.
Контрольные вопросы и задания 1. Для задачи решения квадратного уравнения ax2+bx+c=0 приведите пример теста, проверяющего «нулевой вариант». 2. Имеется следующая задача. Даны три натуральных числа a, b, c, которые представляют собой длины сторон треугольника. Проверить, является ли этот треугольник равносторонним. Для данной задачи приведите пример некорректных данных (предполагается, что три вводимых числа действительно натуральные). 3. Для следующих вариантов заданий написать программу, максимально устойчивую к некорректным данным и снабженную надежной защитой от ошибок. Придумать для заданий систему структурных и функциональных тестов с указанием цели каждого тестирования и описанием ожидаемой реакции.
Варианты заданий 1) Даны три целых неотрицательных числа a, b, c, являющихся длинами сторон треугольника. Проверить, является ли он равносторонним, равнобедренным (в этом случае надо указть длину неравной стороны) или разносторонним. 2) Найти с максимальной точностью все вещественные и комплексные корни квадратного уравнения ax2+bx+c=0. 3) Составить программу вычисления числа сочетаний используя для числовых данных только тип integer. Вычислить с помощью программы 4) Даны три натуральных числа, являющихся длинами сторон треугольника. Определить при каком упорядочении они составляют арифметическую прогрессию. 5) Составить программу привидения общего уравнения кривой второго порядка параболического типа к каноническому виду с определением того, какой геометрический образ определяет это уравнение. При развороте осей выбирать один из возможных углов. 6) Составить программу деления двух многочленов, то есть определения коэффициентов частного и остатка. 7) Составить программу сложения двух простых дробей, представленных парами (m,n)=m/n. Для числовых данных использовать только тип integer.
Литература
1. Гласс Р. Руководство по надежному программированию./ Пер. с англ. М.: Мир, 1981. – 382с. 2. Джонстон Р. Учитесь программировать. / Пер.с англ. М.: Финансы и статистика, 1989. – 368с. 3. Информатика: учебник /Под ред. Н.В. Макаровой. – М.: Финансы и статистика, 1999. – 768с. 4. Кнут Д. Искусство программирования для ЭВМ /Пер. с англ Т1. Основные алгоритмы. М.: Мир, 1976. – 735с.; Т2. Получисленные алгоритмы. М.: Мир, 1977. – 724с. 5. Липаев В.В. Проектирование программных средств. М.: Выс.шк., 1990. – 303с. 6. Липский В. Комбинаторика для программистов /Пер. с польск. М.: Мир, 1988. – 213 с. 7. Майерс Г. Надежность ПО. / Пер. с англ. М.: Мир, 1980. – 360с. 8. Разработка САПР: в 10 кн. Кн.3: Федоров В.С., Гуляев Н.Б. Проектирование программного обеспечения САПР. М.: Высш. шк., 1990. – 159с.
Методические указания к практическим занятиям по курсу «Надежность информационных систем» для студентов дневного обучения
Составители: Бугаев Юрий Владимирович, Полушина Ольга Львовна
Редактор Н.А. Сотникова Корректор Н.В. Бургонова
Подписано в печать... Формат 60x90 1/16. Бумага для множительныхаппаратов, офсетная печать. Усл. п.л. 1,75. Уч. - изд. л.1,5. Тираж 100 экз. Изд. N 24. Заказ 362. Бесплатно.
по дисциплине « Ремонт и надежность машин » на тему: «Методика обработки отказов автотракторных двигателей»
Вариант № 120
Выполнил: студент 45 группы факультета ТС в АПК Левин Ю.А. Проверил: к.т.н. Чепурин А.В.
Москва 2012
Дата добавления: 2015-04-30; Просмотров: 526; Нарушение авторских прав?; Мы поможем в написании вашей работы! Нам важно ваше мнение! Был ли полезен опубликованный материал? Да | Нет |