Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Увеличение точности вычислений до 30-40 значащих цифр [D7, WinXP]


Roman-555 ©   (2010-05-05 14:09:00) 

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

Есть система нелинейных уравнений с 9-ю переменными. При решении приходится находить обратную матрицу для матрицы Якоби. На "простых" матрицах (с небольшими числами вроде "1", "3", "-2" и малых размерностей) обратная матрица находится легко и правильно. Но в случае матрицы Якоби в моей задаче используются числа вроде "15067.908886...". Я нахожу обратную матрицу, но при перемножении ее и исходной получается не совсем единичная матрица. Некоторые строки вычисляются относительно точно (т. е., например, 9-я строка скопировання из watch: (-4,6642160968e-09, 1,5704483588e-08, 3,1408967176e-08, 1,4695463784e-08, -3,6544084438e-09, 3,2663929683e-10, 4,0296994433e-08, -7,4864776945e-09, 0,99999977354)), а другие выглядят подобным образом (1-я строка): (-1,0618292545, 63,621947092, 127,24389418, 63,619455455, -1,0563410126, 35,543700645, 125,74593629, -80,130245746, -945,80434479).

Все данные хранятся в статических массивах 9*9, элементы которых имеют тип данных extended.

Предполагаю, что причина тут в точности вычислений (extended содержит 18-20 значащих цифр), тем более, что Excel считает примерно так же криво (точность расчетов в Excel 15-16 значащих цифр).

Кстати, интересный факт, при перемножении обратной матрицы и исходной "правильно"(т. е. в виде (1 0 0 0..)) выглядят 3,6,7,8 и 9 строки, а "неправильно" 1, 2, 4, 5.

Проблема в том, что конкретных данных на данный момент для отладки нет, есть только примерные величины.

В итоге вопросы:

1.Возможно существуют какие-либо библиотеки или что-то в этом роде, для более точных расчетов. Нужны ссылки, названия, возможно какие-то основы.

2.Если нет, то какой-нибудь совет как это можно реализовать. Конечно у меня мысли есть, но боюсь, что они слишком дилетантские и нерациональные.


Anatoly Podgoretsky   (2010-11-16 16:57:00) [1]

> Юлай  (16.11.2010 12:10:05)  [5]

if (Get8087CW and 256) = 0 then Set8087CW(Get8087CW or 256);

Set8087CW(Get8087CW or 256);


Юлай   (2010-11-16 12:11:00) [2]

В Delphi 7 у меня была похожая проблема. Выглядела она так. Запускаем прогу, точность - достаточная. После вызова функции

function SelectDirectory(const Caption: string; const Root: WideString;
 var Directory: string): Boolean;

точность неожиданно падала. Расследование показало, что точность падает после вызова ShBrowseForFolder, которая вызывается в SelectDirectory.  Сама по себе ShBrowseForFolder - это внешняя функция библиотеки shell32.dll.
Как решение наше статью про Set8087CW и про Get8087CW. Эксперимент показал, что до вызова SelectDirectory 9-й бит переменной полученной через Get8087CW был равен единице и точность была высокой. После вызова функции SelectDirectory 9-й бит переменной полученной через Get8087CW становился равным нулю и точность резко падала. Для меня резко, означает ошибки при работе с матрицами для полинома 10-го и более высокого порядка. Чтобы не париться перед работой с полиномами сделал дополнительный блок:

if (Get8087CW and 256) = 0 then Set8087CW(Get8087CW or 256);

Сейчас все работает. Хотя иногда переключаюсь насильно на менее точные расчеты, но более быстрые через:

if (Get8087CW and 256) <> 0 then Set8087CW(Get8087CW xor 256);


Юлай   (2010-11-16 12:10:00) [3]

В Delphi 7 у меня была похожая проблема. Выглядела она так. Запускаем прогу, точность - достаточная. После вызова функции

function SelectDirectory(const Caption: string; const Root: WideString;
 var Directory: string): Boolean;

точность неожиданно падала. Расследование показало, что точность падает после вызова ShBrowseForFolder, которая вызывается в SelectDirectory.  Сама по себе ShBrowseForFolder - это внешняя функция библиотеки shell32.dll.
Как решение наше статью про Set8087CW и про Get8087CW. Эксперимент показал, что до вызова SelectDirectory 9-й бит переменной полученной через Get8087CW был равен единице и точность была высокой. После вызова функции SelectDirectory 9-й бит переменной полученной через Get8087CW становился равным нулю и точность резко падала. Для меня резко, означает ошибки при работе с матрицами для полинома 10-го и более высокого порядка. Чтобы не париться перед работой с полиномами сделал дополнительный блок:

if (Get8087CW and 256) = 0 then Set8087CW(Get8087CW or 256);

Сейчас все работает. Хотя иногда переключаюсь насильно на менее точные расчеты, но более быстрые через:

if (Get8087CW and 256) <> 0 then Set8087CW(Get8087CW xor 256);


Leonid Troyanovsky   (2010-05-05 18:34:00) [4]


> Roman-555   (05.05.10 14:09)  

> Есть система нелинейных уравнений с 9-ю переменными. При
> решении приходится находить обратную матрицу для матрицы
> Якоби.

Надо посчитать или оценить макс и мин собственные значения
матрицы. Если они отличаются в 1000 и более - это проблема.
Но, и решений было выработано немало, IMHO, еще в 70-80 годах
прошлого века.

Кста, были и методы, не требующие обращения матрицы, а токмо
решения системы ЛУ (в т.ч. итерационные), что, ЕМНИП, проще.

--
Regards, LVT.


Dimka Maslov   (2010-05-05 14:48:00) [5]

Точность можно потерять и при простом повороте координатной системы, если система уравнений плохо обусловлена, когда мы имеем дело с малыми разностями двух больших чисел.
В моей практике инженерных расчётов для матрицы порядка 200х200 обращение даёт приемлемый по точности результат (ошибка не более 0.5%) даже при использовании типа double.
Поэтому если даже при 9х9 точность неприемлема, увеличение количества значащих цифр вряд-ли поможет, надо просто искать другой метод решения.


MBo   (2010-05-05 14:35:00) [6]

Какой метод обращения матрицы используется - прямой (Гаусса, LU) или итерационный (Шульца, Фаддеева)?


Игорь Шевченко   (2010-05-05 14:32:00) [7]

http://www.delphimaster.ru/cgi-bin/forum.pl?id=1273042460&n=18


Наверх

Титульная страница Поиск, карта сайта Написать письмо