Модераторы: Poseidon, Snowy, bems, MetalFan
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Анализ корректности результатов вычислений, Написал статью, хочу критики 
:(
    Опции темы
zalex
Дата 5.4.2006, 22:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 129
Регистрация: 13.5.2005

Репутация: 2
Всего: 2



Автор:Захарченко Александр



Анализ корректности результатов математических вычислений.

Хуже неработающей программы может быть только программа, работающая некорректно, то есть функционирующая по алгоритму, отличному от алгоритма, для реализации которого она создавалась. Причины некорректности функционирования программ кроются в:
– грубых промахах программистов;
– неучёте всех возможных входных данных;
– неучёте некоторых не всегда очевидных тонкостей работы используемых операторов, процедур и функций.
Некорректность работы программных реализаций математических вычислений, к сожалению, не редкость, особенно среди начинающих программистов. Поэтому целью данной работы стало описание аппарата, позволяющего судить об арифметической правильности результатов, полученных в ходе вычислений. В основе такого анализа лежит использование специальных объектов – исключительных ситуаций (далее ИС) - Exceptions.
Исключительные ситуации – это объекты, создаваемые в ходе выполнения приложения в особо важных случаях, предназначенные для информирования в первую очередь программиста о возникновении таких случаев. Концепция использования ИС сводится к тому, что программист должен предусмотреть реакцию программы на возникающие исключительные ситуации.
Далее будут рассмотрены все типы случаев, при которых результаты вычислений нельзя считать арифметически корректными и возникающие при этом ИС. Работа с целыми и вещественными числами рассматривается отдельно, что связано с различными машинными реализациями представлений и операций для этих чисел.
Перед непосредственным рассмотрением случаев появления арифметически некорректного результата и, как следствие, ИС, необходимо понять каким образом компилятор преобразует математические выражения в машинные коды.
Во-первых, все выражения вычисляются поэтапно, то есть из выражения выделяются два аргумента с более высоким приоритетом элементарной операции (+,-,/ , * и т.д.), выделенному выражению генерируется соответствующий машинный код проверки арифметической корректности полученного результата, который в случае обнаружения некорректности создаёт ИС класса, соответствующего типу возникшей ситуации. Затем, из исходного выражения выделяется следующая пара операндов и т.д.
Во-вторых, при записи машинного кода каждой элементарной арифметической операции происходит расширение разрядностей операндов (и, как следствие – результата операции) до максимально возможной. Для целых чисел это 32 битное представление, для чисел с плавающей запятой это представление Extended.

Типы случаев, приводящих к арифметически некорретным результатам при работе с целыми числами.

Деление на ноль. При обнаружении деления на ноль возникает ИС класса EDivByZero. Пример кода, приводящего к такой ситуации ниже:
Код

a:=0;
b:=c div a;

Целочисленное переполнение. Если в процессе выполнения элементарной арифметической операции разрядность результата превышает число разрядов, выделенных для его хранения, результат урезается, а возникшая ситуация называется целочисленным переполнением. Такой результат нельзя считать арифметически корректным, и при обнаружении целочисленного переполнения возникает ИС класса EIntOverflow. Пример кода, приводящего к такой ситуации ниже:
Код

Var a,b,c:LongWord;
Begin
a:=2000000000;
b:=3000000000;
c:=a+b;


Внимание. Для того, что бы компилятор генерировал код, способный обнаруживать целочисленное переполнение, необходимо указать директиву {$Q+}.
Выход за диапазон. Целые числа используются для нумерации отдельных элементов массивов, строк и …значений целых чисел. При указании номера элемента, не соответствующего ранее заявленному диапазону, возникает ситуация выхода за диапазон, сопровождающаяся исключительной ситуацией класса ERangeError. Примеры кода, приводящего к такой ситуации ниже:

Код

Var a:Byte;
      b:Word; 
Begin
b:=270;
a:=b;


и
Код

Var a: array of byte;
Begin
SetLength(a,5);
a[6]:=3;

Внимание. Для того, что бы компилятор генерировал код, способный обнаруживать выход за диапазон, необходимо указать директиву {$R+}.
Перечисленными тремя типами описываются все случаи, приводящие к арифметической некорректности результатов вычислений. Таким образом, общий шаблон процедуры/функции, работающей с вычислениями с целыми числами в общем случае должен иметь подобный вид:
Код

{$R+}
{$Q+}
Procedure MyProcedure (…);
Var…;
Begin
Try
 {здесь помещается код вычислений}
 Except
 On EDivByZero do {код обработки ИС};
 On EIntOverflow do {код обработки ИС};
 On ERangeError do {код обработки ИС};
 {код обработки прочих, не вычислительных ИС}
 End;
End;
{$R-}
{$Q-}


Типы случаев, приводящих к арифметически некорректным результатам при работе с вещественными числами.

Деление на ноль. При обнаружении деления на ноль возникает ИС класса EZeroDivide. Пример кода, приводящего к такой ситуации ниже:
Код

a:=0;
b:=c/a;


Переполнение. Переполнением называется случай, при котором значение модуля результата математической операции превышает модуль максимального значения, которое может быть представлено с помощью используемой разрядности, вследствие чего результат урезается. Так же к переполнению относятся случаи присвоения переменной значения, модуль которого больше модуля максимально представимого числа в разрядности этой переменной. Такие ситуации сопровождаются возникновением ИС класса EOverflow. Примеры кода, приводящего к такой ситуации ниже:
Код

Var a, b, c: Extended;
Begina:=1.1e+4932;
b:=1.1e+4932;
c:=a+b;


и
Код

Var a, b: Extended;
Begina:=1.1e+4932;
b:=exp(a);


и
Код

Var a: Extended;
       b: Double;
Begin
a:=1.1e+4932;
b:= a;


Потеря порядка. Потерей порядка называется случай, при котором значение модуля результата математической операции оказывается меньшим модуля минимального значения, представимого с помощью используемой разрядности, вследствие чего результат обнуляется. Так же к потере порядка относятся случаи присвоения переменной значения, модуль которого меньшего модуля минимально представимого числа в разрядности этой переменной. Такие случаи сопровождаются возникновением ИС класса EUnderflow. Примеры кода, приводящего к такой ситуации ниже:
Код

Var a, b, c: Extended;
Begin
a:=3.6e-4951;
b:=3.6e-4951;
c:=a*b;


и
Код

Var a, b: Extended;
Begin
a:=3.6e-4951;
b:=exp(a);


и
Код

Var a: Extended;
      b:Double;
Begin
a:=3.6e-4951;
b:=a;

Внимание. Математическими операциями с вещественными числами занимается математический сопроцессор. Для того, что бы сопроцессор был чувствителен к обнаружению потери порядка, необходимо установить соответствующую маску его ИС, например следующим образом:
Код

SetExceptionMask(GetExceptionMask-[ExUnderFlow]);


Использование неверных аргументов функций. Иногда возможны случаи, при которых в качестве входных параметров математических и финансовых функций передаются величины, не соответствующие требуемым диапазонам. Такие случаи сопровождаются возникновением ИС классов EInvalidOp или EInvalidArgument, в зависимости от используемых функций. Примеры кода, приводящего к такой ситуации ниже:
Код

Var a, b: Single;
Begin
a:=-4;
b:=arcsin(a);


и
Код

Var a: Extended;
Begin
a:=InterestPayment(-100,15,67,56,76,ptStartOfPeriod);


Таким образом, выше были рассмотрены все типы случаев, приводящих к арифметической некорректности результатов вычислений с вещественными числами. В общем случае, для учета всех ИС, возникающих при вычислительной работе с вещественными числами, соответствующие процедуры/функции должны иметь подобный вид:
Код

Procedure MyProcedure (…);
Var…;
Begin
SetExceptionMask(GetExceptionMask-[ExUnderFlow]);
Try {здесь помещается код вычислений} 
Except 
On EZeroDivide do {код обработки ИС};
 On EOverflow do {код обработки ИС};
 On EUnderflow do {код обработки ИС};
 On EInvalidOp do {код обработки ИС};
 On EInvalidArgument do {код обработки ИС}; 
{код обработки прочих, не вычислительных ИС}
 End;
End;


Это сообщение отредактировал(а) zalex - 6.4.2006, 00:04
PM MAIL   Вверх
cardinal
Дата 5.4.2006, 22:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Инженер
****


Профиль
Группа: Экс. модератор
Сообщений: 6003
Регистрация: 26.3.2002
Где: Германия

Репутация: 2
Всего: 99



Я бы добавил скобки с введением сокращения ИС
Исключительные ситуации (в дальнейшем ИС)
или просто
Исключительные ситуации (ИС)
Так ИМХО понятней будет...


--------------------
Немецкая оппозиция потребовала упростить натурализацию иммигрантов
В моем блоге: Разные истории из жизни в Германии

"Познание бесконечности требует бесконечного времени, а потому работай не работай - все едино".  А. и Б. Стругацкие
PM   Вверх
zalex
Дата 5.4.2006, 22:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 129
Регистрация: 13.5.2005

Репутация: 2
Всего: 2



Спасибо, исправил.
PM MAIL   Вверх
maxim1000
Дата 5.4.2006, 23:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник
Сообщений: 3334
Регистрация: 11.1.2003
Где: Киев

Репутация: 4
Всего: 110



Цитата(zalex @ 5.4.2006, 21:28 Найти цитируемый пост)
чудить

наверное, судить... ну это так... просто заметил


Цитата(zalex @ 5.4.2006, 21:28 Найти цитируемый пост)
использование специальных объектов Windows – исключительных ситуаций (далее ИС) - Exceptions

хм... не уверен, что исключения являются объектами системы
в MSDN есть описание исключений, но там написано, что в основном это делается средствами компилятора
для C++ исключения, описанные в стандарте, реализуются самим компилятором без использования ресурсов системы
кроме того в компилятор от Microsoft встраиваются __try и __except, именно они упоминаются в MSDN, но к стандарту C++ отношения не имеют и являются результатом творчества MS

исходя из этого, мне кажется, что в Delphi большинство исключений реализовано на уровне компилятора (кроме, возможно, деления на ноль)...


--------------------
qqq
PM WWW   Вверх
zalex
Дата 5.4.2006, 23:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 129
Регистрация: 13.5.2005

Репутация: 2
Всего: 2



Угу. Честно копать нет охоты (статью только оформил), но всё что под рукой указывает на то, что Вы правы. Исправлю.
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Общие вопросы"
SnowyMetalFan
bemsPoseidon
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, MetalFan, bems, Poseidon, Rrader.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0468 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.