Форум: "Основная";
Текущий архив: 2005.02.27;
Скачать: [xml.tar.bz2];
ВнизТочность/погрешность вычеслений. Найти похожие ветки
← →
Vaitek © (2005-02-09 16:57) [0]Я краем уха слышал, что в универах на тему погрешности в вычислениях даже отдельно курсы читают. Но мне никто не читал.
Поэтому вопрос:
А какие использются приемы для минимизации вычеслительных погрешностей? Какое типы использовать? Какие действия предпочтительнее, а какие лучше избегать?
Еще у меня часто бывает так, что во время расчетов вместо чистого нуля в переменную попадает число типа 0.00000001693274
А дальше из за него получаются ошибки в расчетах. Или еще бывает вместо 1 -> 0.999999983243. Тоже не приятно, как со всем этим бороться?
← →
Lord Zmiy © (2005-02-09 17:03) [1]сделай допустимую погрешность и говори что если число 0,99999999 и т.д. то число равно нулю
предмет называется Стандартизация и сертификация ... много всяких бесполезных формул а все все равно сводится к округлению :)
← →
Vaitek © (2005-02-09 17:05) [2]Округление я и сам могу сделать. Правда предел точности где-то 10^-6. Я почему-то думал что должно быть точнее. Тип Double.
← →
Vaitek © (2005-02-09 17:09) [3]Да и когда начинать ловить кривые дроби? Чем раньше тем лучше?
← →
Александр Иванов © (2005-02-09 17:11) [4]Lord Zmiy © (09.02.05 17:03) [1]
если число 0,99999999 и т.д. то число равно нулю
Странно вы округляете
← →
Vaitek © (2005-02-09 17:13) [5]Ну он имел в виду единицу.
← →
Юрий Зотов © (2005-02-09 18:25) [6]> Vaitek
http://www.delphikingdom.com/asp/viewitem.asp?catalogid=374
Там найдете объяснения всем "чудесам" и рекомендации по борьбе с ними.
← →
Jeer © (2005-02-09 19:08) [7]Юрий Зотов © (09.02.05 18:25) [6]
К сожалению, это не совсем то.
Это особенности единичных вычислений.
В том же случае, когда алгоритм вычислений составной, необходимо руководствоваться определенными правилами порядка вычислений.
Есть такое понятие в теории погрешностей, как "распространение погрешности".
Здесь нет места и времени для объяснения, но главное - вычитание должно производится как можно ближе к концу локального или глобального процесса вычислений.
← →
Юрий Зотов © (2005-02-09 19:22) [8]> Jeer © (09.02.05 19:08) [7]
Я в курсе. Лет 25. Только не все эти правила вполне однозначны (многое зависит от алгоритма и значений данных), а самое главное, что здесь действительно "нет места и времени для объяснения". На эту тему целые книги написаны.
Начинать же в любом случае надо с простого понимания того, что это такое - машинная арифметика с плавающей точкой.
← →
Vaitek © (2005-02-09 19:42) [9]Статья в избранном, спасибо.
Чую придется глубоко зарываться, а то такую прогу навоял, а она считает немного криво.
Проблема в том, что расчет действительно составной. Задача сводится к серии систем линейных уравнений. Число уравнений в систем от 9 до 11, так что ручками совсем не катит по брейкпоинтам лазить. Плюс кое где есть кодой такой примерно:
If t <> 0 then e := 1/t;
А теперь все представили, если t = 0.00000001 8-)
А ошибка - накапливается и все..............
Удалось добится предельной точности ~ 0.0001 - 0.001 - дальше никуда.
Код не привожу, чтобы поберешь ваши нервы. Да и не влезет он сюда.
← →
Юрий Зотов © (2005-02-09 21:08) [10]> Vaitek © (09.02.05 19:42) [9]
> If t <> 0 then...
Самое простое - переход к типу Extended с выставлением соответствуещего режима FPU. Это помогает, но не всегда спасает.
Для примера - вот возможный (но не всегда приемлемый по смыслу задачи) вариант:
if Abs(t) >= Eps then...
где Eps - заранее вычисленное (один раз, при старте программы) машинное эпсилон. Что это такое - см. в статье.
> Удалось добится предельной точности ~ 0.0001 - 0.001 - дальше
> никуда.
Обычно это достигается уже вылизыванием алгоритма. Простейший пример - для компьютера A+B-C и A-C+B может быть совсем не одно и то же. Что будет, если значения A и C очень близки друг к другу, а значение B на много порядков меньше?
← →
Vaitek © (2005-02-10 12:08) [11]Microsоft на мыло!!!!
Вставил в начале вычеслений:
Set8087CW(Get8087CW or $0100);
Земенил Double на Extended.
Все расчеты с углами перевел в радианы из градусов.
Кое-где изменил формулы расчетов, минимизируя деления и вычитания.
Получил увеличение точности до 10^-6 10^-8.
Но максимальный прирост был от
Set8087CW(Get8087CW or $0100);
Пример:
Var
a,b,c :Extended;
Begin
a := 0.0;
b := 23.10;
c := a-b; //c = -23.100000381
End;
Var
a,b,c :Extended;
Begin
Set8087CW(Get8087CW or $0100);
a := 0.0;
b := 23.10;
c := a-b; //c = -23.1
End;
На всякий случай напихал этот Set8087CW перед каждым циклом расчетов и ввода исходных данных.
Статья - супер.
Всем спасибо!
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2005.02.27;
Скачать: [xml.tar.bz2];
Память: 0.47 MB
Время: 0.067 c