Если это ваш первый визит, рекомендуем почитать справку по форуму. Для размещения своих сообщений необходимо зарегистрироваться. Для просмотра сообщений выберите раздел. |
Анализ корректности результатов математических вычислений. Моя статья. |
Философия, технологии, алгоритмы! |
|
Опции темы |
05.04.2006, 23:07 | #1 |
Покинул БВФ
Сообщений: 469
Регистрация: 28.06.2005
Не в сети |
Анализ корректности результатов математических вычислений. Моя статья.
Автор:Захарченко Александр [email protected] Анализ корректности результатов математических вычислений. Хуже неработающей программы может быть только программа, работающая некорректно, то есть функционирующая по алгоритму, отличному от алгоритма, для реализации которого она создавалась. Причины некорректности функционирования программ кроются в:– грубых промахах программистов; – неучёте всех возможных входных данных; – неучёте некоторых не всегда очевидных тонкостей работы используемых операторов, процедур и функций. Некорректность работы программных реализаций математических вычислений, к сожалению, не редкость, особенно среди начинающих программистов. Поэтому целью данной работы стало описание аппарата, позволяющего cудить об арифметической правильности результатов, полученных в ходе вычислений. В основе такого анализа лежит использование специальных объектов – исключительных ситуаций (далее ИС) -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; BeginSetLength(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; Begin a:=1.1e+4932; b:=1.1e+4932; c:=a+b; и Var a, b: Extended; Begin a:=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; Begina:=3.6e-4951; b:=exp(a); и Var a: Extended; bouble; 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…; BeginSetExceptionMask(GetExceptionMask-[ExUnderFlow]); Try {здесь помещается код вычислений} Except On EZeroDivide do {код обработки ИС}; On EOverflow do {код обработки ИС}; On EUnderflow do {код обработки ИС}; On EInvalidOp do {код обработки ИС}; On EInvalidArgument do {код обработки ИС}; {код обработки прочих, не вычислительных ИС} End; End; В общем кто что скажет? |
06.04.2006, 01:03 | #2 |
Форумец
Сообщений: 166
Регистрация: 02.08.2005
Возраст: 44
Не в сети |
реально из всего описаного попадалово только с целочисленным делением на ноль, и то попадалово очень спецефическое и лехко обходимое.
а с флотами все описаное и циклическое переполнение у целых чисел - нет проблемы в этом никакой, такие ситуации тоже легко можно не допускать. в тексте есть неточности... например результат выражения будет размера максимального аперанда в этом выражении (с++, в паскале не помню). тема "зачем эти исключения обрабатывать" в докладе не раскрыта. и зачем включать эти исключения ??? чтобы потом обрабатывать ? типа человек это такое животное которое находит себе трудности на ровном месте, а потом мужественно их преодолевает так ? где потребовалась такая научная работа ? |
06.04.2006, 07:14 | #4 |
Форумец
Сообщений: 2,045
Регистрация: 27.08.2003
Не в сети |
Элементарщина, потому и ерунда.
Главный гемор - примение юзером не того алгоритма, который следовало. А ошибка в исходных данных, когда эти данные невозможно или слишком трудоемко проверить - вообще ужас. Поясняю. Например, есть некий набор исходных данных, скажем, пара тысяч значений, отражающих физические свойства некоего объекта. Проверить стопроцентную достоверность каждой цифры возможно только экспертом или даже набором экспертов. Плюс ошибки ввода (например, самая простая - неверная единица измерения, вместо метра - километр, и ошиба одного из параметров - порядки). Но, если даже ошибка параметра - порядок, то конечный результат (набор выходных данных в количестве нескольких тысяч) будет сильно похож на правду, но правдой не являться. Никакими програмистскими ухищрениями проблема не решается. Конечно, применяются входные и выходные "параметрорезки" - несуразные с прикладной точки зрения значения отсекаются, но так можно только понизить вероятность неверного расчета, не более того. |
06.04.2006, 11:27 | #5 | |
бибизьян
Сообщений: 3,031
Регистрация: 17.02.2004
Не в сети |
Цитата:
Вот так всегда, у всех эксепшены, а у меня - бесконечность........ Тоска............. |
|
06.04.2006, 11:52 | #6 | |
back 4 good
Сообщений: 19,298
Регистрация: 23.04.2003
Не в сети |
Цитата:
|
|
06.04.2006, 11:58 | #7 |
бибизьян
Сообщений: 3,031
Регистрация: 17.02.2004
Не в сети |
vi0 Дадад. Непаханное поле деятельности. Возможные темы статей:
"Зависимость между числом ошибок, допускаемых программистами в понедельник, от литража, поглощенного в ночь с пятницы на понедельник", "Запавший SHIFT как дестабилизирующий фактор" и т.д. |
09.04.2006, 19:40 | #10 | |
АНТИЛЮМПЕНКА
Сообщений: 7,645
Регистрация: 03.09.2005
Возраст: 40
Не в сети |
Цитата:
|
|
15.04.2006, 21:37 | #17 |
Форумец
Сообщений: 144
Регистрация: 02.07.2005
Возраст: 42
Не в сети |
анал логично не понял об чем статья
в принципе можно было написать про галочки на вкладке Compiler в разделе Runtime Errors а вобще головой надо думать, вон у французов ракета Aerin наибнулась изза буфер оверфлоу, неиспользованая горючка разлетелась на полторы тыщи гектаров. списали на недостаточную продуманость компилятора а вы все про деление на ноль бугага:-) афтар брось паскаль учи олбанцкей |