IPB
ЛогинПароль:

> Правила раздела!

1. Заголовок или название темы должно быть информативным !
2. Все тексты фрагментов программ должны помещаться в теги [code] ... [/code] или [code=pas] ... [/code].
3. Прежде чем задавать вопрос, см. "FAQ" и используйте ПОИСК !
4. НЕ используйте форум для личного общения!
5. Самое главное - это раздел теоретический, т.е. никаких задач и программ (за исключением небольших фрагментов) - для этого есть отдельный раздел!

 
 Ответить  Открыть новую тему 
> Обработка ошибок
сообщение
Сообщение #1


Гость






Существует ли в паскале обработка ошибок, на подобии бейсиковской onerror?
 К началу страницы 
+ Ответить 
сообщение
Сообщение #2


Гость






Встроенная (я про Турбо-Паскаль, конечно, современные-то компиляторы имеют блок Try ... Except) - нет, добавить можно (с использованием ассемблерных вставок или директивы Inline)... Пример - тут:
как отлавливать исключение в Турбо Паскале 7.0
 К началу страницы 
+ Ответить 
сообщение
Сообщение #3





Группа: Пользователи
Сообщений: 6
Пол: Мужской

Репутация: -  0  +


Мде(
Может есть способ проверить перед умножением двух чисел extended, будет переполнение или нет?
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #4


Гуру
*****

Группа: Пользователи
Сообщений: 1 168
Пол: Мужской
Реальное имя: Сергей Андрианов

Репутация: -  28  +


Конечно есть.
Если оба числа по модулю больше 10^154, то переполнение будет обязательно, а если хотя бы одно из них - то возможно.
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #5


Гость






Цитата
Если оба числа по модулю больше 10^154, то переполнение будет обязательно
Правда? Ну, давай посмотрим:
Прикрепленное изображение

Что я делаю не так? Где переполнение? dry.gif
 К началу страницы 
+ Ответить 
сообщение
Сообщение #6


Уникум
*******

Группа: Пользователи
Сообщений: 6 823
Пол: Мужской
Реальное имя: Лопáрь (Андрей)

Репутация: -  159  +


Цитата(Flover @ 5.12.2007 19:24) *
есть способ проверить перед умножением двух чисел extended, будет переполнение или нет?
Конечно, есть. И конечно, не такой, как у andriano. Проверка на уровне "возможно" вряд ли устроит в реальной ситуации (даже если не ошибиться в диапазоне yes2.gif )..

Можно проверять логарифм. Как известно, логарифм произведения равен сумме логарифмов. Вычисли натуральные логарифмы модулей сомножителей и сложи их. Если получится меньше, чем примерно 11356.5 (значение можно уточнить, но это непринципиально), то смело умножай, если больше - то не стоит.. smile.gif И есть еще одно "но": надо следить, чтоб никакой из сомножителей не был равен нулю, иначе логарифм выдаст ошибку. Но при хотя бы одном сомножителе, равном нулю, за переполнение произведения опасаться нечего, так что все в результате должно выглядеть примерно так:
if (a=0) or (b=0) or (Ln(Abs(a))+Ln(Abs(b))<=11356.5) then c:=a*b;


Если ты можешь приблизительно предсказать величину своих чисел, то можно обойтись без логарифмов. Например, если ты уверен, что все значения больше, скажем, единицы, то можно перемножить обратные величины. Это произведение нужно сравнить примерно с 5e-4932 :
if 1/Abs(a)/Abs(b)>5e-4932 then c:=a*b

Этот способ кажется проще, но в нем есть условности и подводные камни, так что я его не стал бы рекомендовать.

И вообще, хотя я все это и написал, рекомендую я все же вернуться к первоначальной идее и выполнить контроль за ошибками smile.gif. Подобные же извращения существено замедлят выполнение программы..


--------------------
я - ветер, я северный холодный ветер
я час расставанья, я год возвращенья домой
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #7


Гуру
*****

Группа: Пользователи
Сообщений: 1 168
Пол: Мужской
Реальное имя: Сергей Андрианов

Репутация: -  28  +


Цитата(Lapp @ 6.12.2007 6:41) *

Конечно, есть. И конечно, не такой, как у andriano. Проверка на уровне "возможно" вряд ли устроит в реальной ситуации

Не могу согласиться.
Если не брать эксперименты из теории чисел, то любые величины, которые могут встретиться в РЕАЛЬНЫХ расчетах, никак не могут превосходить по абсолютной величине 10 в степени несколько десяков. Да и десятки в данном случае - большая экзотика.
Поэтому появление ХОТЯ БЫ ОДНОГО числа больше, скажем, 10^154 уже однозначно свидетельствует об ошибке.
Таким образом, если нас интересуют вычисления ради вычислений, можно, конечно, поизвращаться, если же нас интересует ответ на конкретный вопрос (решение конкретной задачи), то даже единственного сомножителя "неразумной" величины достаточно, чтобы сделать вывод о том, что в предшествующих вычислениях содержится ошибка?
А зачем еще нам может понадобиться проверка?
Только затем, чтобы выявить и аккуратно обработать ошибку вместо того, чтобы допусить аварийное завершение программы.

PS. Ну не помню я навскидку пределы изменения extended. Казалось, что порядка 10^308. Возможно, это относится к какому-то другому типу. В любом случае, в реальных расчетах такие числа не используются.

Сообщение отредактировано: andriano -
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #8


Уникум
*******

Группа: Пользователи
Сообщений: 6 823
Пол: Мужской
Реальное имя: Лопáрь (Андрей)

Репутация: -  159  +


Цитата(andriano @ 6.12.2007 8:00) *
Если не брать эксперименты из теории чисел, то любые величины, которые могут встретиться в РЕАЛЬНЫХ расчетах,
andriano, уже не в первый раз, когда тебе укажут на ошибку, ты пытаешься выкрутиться и сказать, что отвечал совсем на другой вопрос. Откуда ты знаешь, какие "эксперименты" проводит автор? ты его спросил?.. Будь добр, отвечай на поставленный вопрос, а не на выдуманный тобой. Если хочешь поговорить о методолгии численного моделирования - пожалуйста, открой другую тему и выясни все, что тебе неясно! Можешь даже попробовать рассказать то, что ясно тебе, а другие пока еще не спросили.. Но - в СВОЕЙ теме.

И если ты считаешь, что это некоторым боком относится к теме - скажи, каким именно и почему. И скажи ДО ответа, а не после.

Цитата(andriano @ 6.12.2007 8:00) *
Ну не помню я навскидку пределы изменения extended. Казалось, что порядка 10^308. Возможно, это относится к какому-то другому типу. В любом случае, в реальных расчетах такие числа не используются.
Так и слышится продолжение: "... и поэтому я снова прав!"
Ну не помнишь - ну не говори! Ты не прав. Признай ошибку - или промолчи на худой конец. Объяснения оставь для мамы. Никого не интересует, что тебе КАЖЕТСЯ и почему..


--------------------
я - ветер, я северный холодный ветер
я час расставанья, я год возвращенья домой
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #9





Группа: Пользователи
Сообщений: 6
Пол: Мужской

Репутация: -  0  +


Цитата
интересуют вычисления ради вычислений

К сожалению задача это предполагает и, если делать проверку, то никаких 'примерно'

Плохо(
Я имел ввиду встроенную проверку, об алгоритмической я и сам сообразил бы.
Мой вариант- делим каждое число на 2, пока оно <=2, записывая каждое деление в i. Таким образом выделяем двоичную экспоненту. Складываем обе экспоненты. Если произведение остатков изначальных чисел(т.е. двоичных мантис) >=2, добавляем к сумме 1.
Ну и если получившаяся сумма >16383(максимальная двоичная экспонента), то переполнение.
Аналогичные танцы с бубном и для деления на чила <1.

Скорей всего разумней отказатся вообще от проверки(
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #10


Гость






Цитата
К сожалению задача это предполагает и, если делать проверку, то никаких 'примерно'
Надо точно? Тогда обрабатывай слово состояния FPU:

function check_overflow(a, b: extended): boolean;
var sw: word;
begin
asm
fld a
fld b
fmul
fnstsw sw
end;
check_overflow := ((sw and $0008) > 0);
end;

var
a, b, c: extended;
CWord: word;

begin
{ a := 3E3000; }
a := 3E1000;
b := 4E3000;


if check_overflow(a, b) then writeln('overflow')
else writeln('a * b = ', a * b);
end.

Незакомментированное значение отработает нормально, закомментированное вызовет переполнение... О чем и будет сообщено...
 К началу страницы 
+ Ответить 
сообщение
Сообщение #11





Группа: Пользователи
Сообщений: 6
Пол: Мужской

Репутация: -  0  +


Спасибо..
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #12


Гуру
*****

Группа: Пользователи
Сообщений: 1 168
Пол: Мужской
Реальное имя: Сергей Андрианов

Репутация: -  28  +


Цитата(Flover @ 6.12.2007 14:26) *

К сожалению задача это предполагает и, если делать проверку, то никаких 'примерно'
Извини, неправильно понял ЦЕЛЬ данного мероприятия - посчитал, что нужно диагностировать ошибку вычислений раньше, чем она приведет к краху программы.
Цитата
Мой вариант- делим каждое число на 2, пока оно <=2, записывая каждое деление в i. Таким образом выделяем двоичную экспоненту. Складываем обе экспоненты. Если произведение остатков изначальных чисел(т.е. двоичных мантис) >=2, добавляем к сумме 1.
Двоичный логарифм числа можно получить гораздо проще, ибо он изначально содержится в представлении числа с плавающей точкой.
Например, для extended логарифм добывается так: (wq - исходное число extended, с - логарифм integer(16))
Код
    asm {лог. по осн.2 (извлечение порядка)}
      mov eax,dword ptr [wq+8]
      and eax,$7fff
      sub eax,16384
      mov c,ax
    end;
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #13





Группа: Пользователи
Сообщений: 6
Пол: Мужской

Репутация: -  0  +


Цитата

asm {лог. по осн.2 (извлечение порядка)}
mov eax,dword ptr [wq+8]
and eax,$7fff
sub eax,16384
mov c,ax
end;

Да, использовать асм умнее. Ток вычесть 16383, и ТП7 вроде 16 битный. Для продолжения еще надо будет экспоенту обнулить.
Но поскольку без асм вставок почти никак, думаю обработку не спросят.
Задача про виртуальный процессор собсно моя задача, прост хотел узнать ее цену.
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #14


Гуру
*****

Группа: Пользователи
Сообщений: 1 168
Пол: Мужской
Реальное имя: Сергей Андрианов

Репутация: -  28  +


Цитата(Flover @ 9.12.2007 16:44) *

Да, использовать асм умнее. Ток вычесть 16383, и ТП7 вроде 16 битный. Для продолжения еще надо будет экспоенту обнулить.
Но поскольку без асм вставок почти никак, думаю обработку не спросят.

Гм...
Паскаль - хороший язык.
Нет, можно, конечно, придумать что-нибудь, что довольно трудно реализовать на Паскале, но легко на Ассемблере, но в подавляющем большинстве случаев это не так.
Приведу аналог предыдущего примера целиком на 16-разрядном Паскале:
var 
qw : extended;
w : array[0..4]of word absolute qw;
с : integer;
begin
...
с := w[4] and $7fff;
с := с-16384;


Сообщение отредактировано: andriano -
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #15





Группа: Пользователи
Сообщений: 6
Пол: Мужской

Репутация: -  0  +


Спасибо. А можно ли qw присвоить значение w[], чтобы обнулить экспонету?
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #16


Гуру
*****

Группа: Пользователи
Сообщений: 1 168
Пол: Мужской
Реальное имя: Сергей Андрианов

Репутация: -  28  +


Вот что у меня получилось:
var
e : extended;
w : array[0..4]of word absolute e;
begin
e := 1234;
writeln('mantiss: ',e/2048.0:1:18);
w[4] := (w[4] and $8000) + $3ffe;
writeln('mantiss: ',e:1:18);
end.


PS. А еще лучше, наверное, так:
var
e,e1 : extended;
w : array[0..4]of word absolute e;
l : integer;
begin
e := 1234;
l := (w[4] and $7fff) - $3fff;
e1 := exp(ln(2.0)*l);
writeln('mantiss: ',e/e1:1:18);
w[4] := (w[4] and $8000) + $3fff;
writeln('mantiss: ',e:1:18);
end.


Сообщение отредактировано: andriano -
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #17





Группа: Пользователи
Сообщений: 6
Пол: Мужской

Репутация: -  0  +


Ага, надо было просто оперировать с w[], мог бы и сам догадаться dry.gif
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 

 Ответить  Открыть новую тему 
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 





- Текстовая версия 28.03.2024 15:13
500Gb HDD, 6Gb RAM, 2 Cores, 7 EUR в месяц — такие хостинги правда бывают
Связь с администрацией: bu_gen в домене octagram.name