![]() |
|
Модераторы: Poseidon, Snowy, bems, MetalFan |
![]()
|
|
| zalex |
|
||||||||||||||||||||||||||||||||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 129 Регистрация: 13.5.2005 Репутация: 2 Всего: 2 |
Автор:Захарченко Александр Анализ корректности результатов математических вычислений. Хуже неработающей программы может быть только программа, работающая некорректно, то есть функционирующая по алгоритму, отличному от алгоритма, для реализации которого она создавалась. Причины некорректности функционирования программ кроются в: – грубых промахах программистов; – неучёте всех возможных входных данных; – неучёте некоторых не всегда очевидных тонкостей работы используемых операторов, процедур и функций. Некорректность работы программных реализаций математических вычислений, к сожалению, не редкость, особенно среди начинающих программистов. Поэтому целью данной работы стало описание аппарата, позволяющего судить об арифметической правильности результатов, полученных в ходе вычислений. В основе такого анализа лежит использование специальных объектов – исключительных ситуаций (далее ИС) - Exceptions. Исключительные ситуации – это объекты, создаваемые в ходе выполнения приложения в особо важных случаях, предназначенные для информирования в первую очередь программиста о возникновении таких случаев. Концепция использования ИС сводится к тому, что программист должен предусмотреть реакцию программы на возникающие исключительные ситуации. Далее будут рассмотрены все типы случаев, при которых результаты вычислений нельзя считать арифметически корректными и возникающие при этом ИС. Работа с целыми и вещественными числами рассматривается отдельно, что связано с различными машинными реализациями представлений и операций для этих чисел. Перед непосредственным рассмотрением случаев появления арифметически некорректного результата и, как следствие, ИС, необходимо понять каким образом компилятор преобразует математические выражения в машинные коды. Во-первых, все выражения вычисляются поэтапно, то есть из выражения выделяются два аргумента с более высоким приоритетом элементарной операции (+,-,/ , * и т.д.), выделенному выражению генерируется соответствующий машинный код проверки арифметической корректности полученного результата, который в случае обнаружения некорректности создаёт ИС класса, соответствующего типу возникшей ситуации. Затем, из исходного выражения выделяется следующая пара операндов и т.д. Во-вторых, при записи машинного кода каждой элементарной арифметической операции происходит расширение разрядностей операндов (и, как следствие – результата операции) до максимально возможной. Для целых чисел это 32 битное представление, для чисел с плавающей запятой это представление Extended. Типы случаев, приводящих к арифметически некорретным результатам при работе с целыми числами. Деление на ноль. При обнаружении деления на ноль возникает ИС класса EDivByZero. Пример кода, приводящего к такой ситуации ниже:
Целочисленное переполнение. Если в процессе выполнения элементарной арифметической операции разрядность результата превышает число разрядов, выделенных для его хранения, результат урезается, а возникшая ситуация называется целочисленным переполнением. Такой результат нельзя считать арифметически корректным, и при обнаружении целочисленного переполнения возникает ИС класса EIntOverflow. Пример кода, приводящего к такой ситуации ниже:
Внимание. Для того, что бы компилятор генерировал код, способный обнаруживать целочисленное переполнение, необходимо указать директиву {$Q+}. Выход за диапазон. Целые числа используются для нумерации отдельных элементов массивов, строк и …значений целых чисел. При указании номера элемента, не соответствующего ранее заявленному диапазону, возникает ситуация выхода за диапазон, сопровождающаяся исключительной ситуацией класса ERangeError. Примеры кода, приводящего к такой ситуации ниже:
и
Внимание. Для того, что бы компилятор генерировал код, способный обнаруживать выход за диапазон, необходимо указать директиву {$R+}. Перечисленными тремя типами описываются все случаи, приводящие к арифметической некорректности результатов вычислений. Таким образом, общий шаблон процедуры/функции, работающей с вычислениями с целыми числами в общем случае должен иметь подобный вид:
Типы случаев, приводящих к арифметически некорректным результатам при работе с вещественными числами. Деление на ноль. При обнаружении деления на ноль возникает ИС класса EZeroDivide. Пример кода, приводящего к такой ситуации ниже:
Переполнение. Переполнением называется случай, при котором значение модуля результата математической операции превышает модуль максимального значения, которое может быть представлено с помощью используемой разрядности, вследствие чего результат урезается. Так же к переполнению относятся случаи присвоения переменной значения, модуль которого больше модуля максимально представимого числа в разрядности этой переменной. Такие ситуации сопровождаются возникновением ИС класса EOverflow. Примеры кода, приводящего к такой ситуации ниже:
и
и
Потеря порядка. Потерей порядка называется случай, при котором значение модуля результата математической операции оказывается меньшим модуля минимального значения, представимого с помощью используемой разрядности, вследствие чего результат обнуляется. Так же к потере порядка относятся случаи присвоения переменной значения, модуль которого меньшего модуля минимально представимого числа в разрядности этой переменной. Такие случаи сопровождаются возникновением ИС класса EUnderflow. Примеры кода, приводящего к такой ситуации ниже:
и
и
Внимание. Математическими операциями с вещественными числами занимается математический сопроцессор. Для того, что бы сопроцессор был чувствителен к обнаружению потери порядка, необходимо установить соответствующую маску его ИС, например следующим образом:
Использование неверных аргументов функций. Иногда возможны случаи, при которых в качестве входных параметров математических и финансовых функций передаются величины, не соответствующие требуемым диапазонам. Такие случаи сопровождаются возникновением ИС классов EInvalidOp или EInvalidArgument, в зависимости от используемых функций. Примеры кода, приводящего к такой ситуации ниже:
и
Таким образом, выше были рассмотрены все типы случаев, приводящих к арифметической некорректности результатов вычислений с вещественными числами. В общем случае, для учета всех ИС, возникающих при вычислительной работе с вещественными числами, соответствующие процедуры/функции должны иметь подобный вид:
Это сообщение отредактировал(а) zalex - 6.4.2006, 00:04 |
||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||
| cardinal |
|
|||
![]() Инженер ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 6003 Регистрация: 26.3.2002 Где: Германия Репутация: 2 Всего: 99 |
Я бы добавил скобки с введением сокращения ИС
Исключительные ситуации (в дальнейшем ИС) или просто Исключительные ситуации (ИС) Так ИМХО понятней будет... -------------------- Немецкая оппозиция потребовала упростить натурализацию иммигрантов В моем блоге: Разные истории из жизни в Германии "Познание бесконечности требует бесконечного времени, а потому работай не работай - все едино". А. и Б. Стругацкие |
|||
|
||||
| zalex |
|
|||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 129 Регистрация: 13.5.2005 Репутация: 2 Всего: 2 |
Спасибо, исправил.
|
|||
|
||||
| maxim1000 |
|
|||
|
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Участник Сообщений: 3334 Регистрация: 11.1.2003 Где: Киев Репутация: 4 Всего: 110 |
наверное, судить... ну это так... просто заметил
хм... не уверен, что исключения являются объектами системы в MSDN есть описание исключений, но там написано, что в основном это делается средствами компилятора для C++ исключения, описанные в стандарте, реализуются самим компилятором без использования ресурсов системы кроме того в компилятор от Microsoft встраиваются __try и __except, именно они упоминаются в MSDN, но к стандарту C++ отношения не имеют и являются результатом творчества MS исходя из этого, мне кажется, что в Delphi большинство исключений реализовано на уровне компилятора (кроме, возможно, деления на ноль)... -------------------- qqq |
|||
|
||||
| zalex |
|
|||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 129 Регистрация: 13.5.2005 Репутация: 2 Всего: 2 |
Угу. Честно копать нет охоты (статью только оформил), но всё что под рукой указывает на то, что Вы правы. Исправлю.
|
|||
|
||||
![]()
|
| Правила форума "Delphi: Общие вопросы" | |
|
|
Запрещается! 1. Публиковать ссылки на вскрытые компоненты 2. Обсуждать взлом компонентов и делиться вскрытыми компонентами
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, MetalFan, bems, Poseidon, Rrader. |
| 0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
| 0 Пользователей: | |
| « Предыдущая тема | Delphi: Общие вопросы | Следующая тема » |
|
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |