Большой Воронежский Форум

Если это ваш первый визит, рекомендуем почитать справку по форуму. Для размещения своих сообщений необходимо зарегистрироваться. Для просмотра сообщений выберите раздел.
Вернуться   Большой Воронежский Форум » Компьютеры и все, что с ними связано » » Программирование
Философия, технологии, алгоритмы!

Ответ
 
Опции темы
Старый 05.04.2006, 23:07   #1   
Покинул БВФ
 
Аватар для zalex
 
Сообщений: 469
Регистрация: 28.06.2005

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

Автор:Захарченко Александр
[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   
Форумец
 
Аватар для VBA b0.3
 
Сообщений: 166
Регистрация: 02.08.2005
Возраст: 44

VBA b0.3 вне форума Не в сети
реально из всего описаного попадалово только с целочисленным делением на ноль, и то попадалово очень спецефическое и лехко обходимое.
а с флотами все описаное и циклическое переполнение у целых чисел - нет проблемы в этом никакой, такие ситуации тоже легко можно не допускать.

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

тема "зачем эти исключения обрабатывать" в докладе не раскрыта.
и зачем включать эти исключения ??? чтобы потом обрабатывать ?
типа человек это такое животное которое находит себе трудности на ровном месте, а потом мужественно их преодолевает так ?

где потребовалась такая научная работа ?
  Ответить с цитированием
Старый 06.04.2006, 01:05   #3   
Форумец
 
Аватар для VBA b0.3
 
Сообщений: 166
Регистрация: 02.08.2005
Возраст: 44

VBA b0.3 вне форума Не в сети
кстати нет ни слова про АНАЛИЗ КОРРЕКТНОСТИ ВЫЧИСЛЕНИЙ в докладе.. тема ни раскрыта,
в чем он заключался ? в детекте исключения ? а потом что ? что делать в этом исключении ?

кг/ам
  Ответить с цитированием
Старый 06.04.2006, 07:14   #4   
Форумец
 
Аватар для zss_vrn
 
Сообщений: 2,045
Регистрация: 27.08.2003

zss_vrn вне форума Не в сети
Элементарщина, потому и ерунда.

Главный гемор - примение юзером не того алгоритма, который следовало. А ошибка в исходных данных, когда эти данные невозможно или слишком трудоемко проверить - вообще ужас.

Поясняю. Например, есть некий набор исходных данных, скажем, пара тысяч значений, отражающих физические свойства некоего объекта. Проверить стопроцентную достоверность каждой цифры возможно только экспертом или даже набором экспертов. Плюс ошибки ввода (например, самая простая - неверная единица измерения, вместо метра - километр, и ошиба одного из параметров - порядки). Но, если даже ошибка параметра - порядок, то конечный результат (набор выходных данных в количестве нескольких тысяч) будет сильно похож на правду, но правдой не являться. Никакими програмистскими ухищрениями проблема не решается.

Конечно, применяются входные и выходные "параметрорезки" - несуразные с прикладной точки зрения значения отсекаются, но так можно только понизить вероятность неверного расчета, не более того.
  Ответить с цитированием
Старый 06.04.2006, 11:27   #5   
бибизьян
 
Аватар для aerin
 
Сообщений: 3,031
Регистрация: 17.02.2004

aerin вне форума Не в сети
Цитата:
#include <stdio.h>

void main()
{
int in_value = 25;
float out_value;

_asm
{
finit
fld in_value
fldz
fdiv
fstp out_value
}

printf( "25%%0=%f\n", out_value );
}
Выдает: 25%0=1.#INF00

Вот так всегда, у всех эксепшены, а у меня - бесконечность........
Тоска.............
  Ответить с цитированием
Старый 06.04.2006, 11:52   #6   
back 4 good
 
Аватар для vi0
 
Сообщений: 19,298
Регистрация: 23.04.2003

vi0 вне форума Не в сети
Цитата:
Сообщение от zalex
Таким образом, выше были рассмотрены все типы случаев, приводящих к арифметической некорректности результатов вычислений
А способы обнаружения ошибок, вызванных программистом, написавшим "-" вместо "+" и "12" вместо "1.2" вы рассматривали?
  Ответить с цитированием
Старый 06.04.2006, 11:58   #7   
бибизьян
 
Аватар для aerin
 
Сообщений: 3,031
Регистрация: 17.02.2004

aerin вне форума Не в сети
vi0 Дадад. Непаханное поле деятельности. Возможные темы статей:
"Зависимость между числом ошибок, допускаемых программистами в понедельник, от литража, поглощенного в ночь с пятницы на понедельник", "Запавший SHIFT как дестабилизирующий фактор" и т.д.
  Ответить с цитированием
Старый 06.04.2006, 11:59   #8   
error #65535
 
Аватар для maximn
 
Сообщений: 5,240
Регистрация: 16.11.2003
Возраст: 24

maximn вне форума Не в сети
узнал много нового, спасибо.
кстати, если кому интересно - моя программа 'Hello world!' уже почти работает.
  Ответить с цитированием
Старый 09.04.2006, 17:39   #9   
Форумец
 
Аватар для M0l0t
 
Сообщений: 5,975
Регистрация: 22.04.2003
Записей в дневнике: 4

M0l0t вне форума Не в сети
Цитата:
Сообщение от maximn
кстати, если кому интересно - моя программа 'Hello world!' уже почти работает.
выложи чтоли, очень хотелось бы взглянуть
  Ответить с цитированием
Старый 09.04.2006, 19:40   #10   
АНТИЛЮМПЕНКА
 
Аватар для Alessia
 
Сообщений: 7,645
Регистрация: 03.09.2005
Возраст: 40

Alessia вне форума Не в сети
Цитата:
Сообщение от maximn
узнал много нового, спасибо.
кстати, если кому интересно - моя программа 'Hello world!' уже почти работает.
Приорала - сталкиваюсь с этой прогой постоянно - но то что ты автор ...короче обалдеть........... в форуме с самим автором ...
  Ответить с цитированием
Старый 09.04.2006, 20:49   #11   
АНТИЛЮМПЕНКА
 
Аватар для Alessia
 
Сообщений: 7,645
Регистрация: 03.09.2005
Возраст: 40

Alessia вне форума Не в сети
maximn, кстати придумала тебе клёвую концовку
{
public static void main(String[] args) {

System.out.println("Hello World!');
}
ГЫ
  Ответить с цитированием
Старый 09.04.2006, 23:04   #12   
Форумец
 
Аватар для M0l0t
 
Сообщений: 5,975
Регистрация: 22.04.2003
Записей в дневнике: 4

M0l0t вне форума Не в сети
alessia, зачем лишняя открывающаяся скобка?
  Ответить с цитированием
Старый 09.04.2006, 23:18   #13   
error #65535
 
Аватар для maximn
 
Сообщений: 5,240
Регистрация: 16.11.2003
Возраст: 24

maximn вне форума Не в сети
alessia, и что за оператор "ГЫ"?
  Ответить с цитированием
Старый 09.04.2006, 23:18   #14   
error #65535
 
Аватар для maximn
 
Сообщений: 5,240
Регистрация: 16.11.2003
Возраст: 24

maximn вне форума Не в сети
Цитата:
Сообщение от M0l0t
выложи чтоли, очень хотелось бы взглянуть
пока отлаживаю, выложу как только пофиксю баги
  Ответить с цитированием
Старый 10.04.2006, 08:26   #15   
АНТИЛЮМПЕНКА
 
Аватар для Alessia
 
Сообщений: 7,645
Регистрация: 03.09.2005
Возраст: 40

Alessia вне форума Не в сети
Цитата:
Сообщение от M0l0t
alessia, зачем лишняя открывающаяся скобка?
Это для лишнего оператора ГЫ
  Ответить с цитированием
Старый 15.04.2006, 20:11   #16   
iUser
 
Аватар для zeroserg
 
Сообщений: 2,623
Регистрация: 15.05.2005

zeroserg вне форума Не в сети
zalex, это для делфи? ну так и надо было написать
  Ответить с цитированием
Старый 15.04.2006, 21:37   #17   
Форумец
 
Аватар для logged in
 
Сообщений: 144
Регистрация: 02.07.2005
Возраст: 42

logged in вне форума Не в сети
анал логично не понял об чем статья
в принципе можно было написать про галочки на вкладке Compiler в разделе Runtime Errors
а вобще головой надо думать, вон у французов ракета Aerin наибнулась изза буфер оверфлоу, неиспользованая горючка разлетелась на полторы тыщи гектаров. списали на недостаточную продуманость компилятора а вы все про деление на ноль бугага:-)
афтар брось паскаль учи олбанцкей
  Ответить с цитированием
Поиск в теме: 


Опции темы

Быстрый переход:

  Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения
BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.


Powered by vBulletin® Version 3.8.7
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd. Перевод: zCarot
Support by DrIQ & Netwind