Модераторы: Daevaorn

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Использование double вместо float, повысится ли точность вычислений? 
:(
    Опции темы
Фантом
Дата 27.8.2012, 12:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Вы это прекратите!
***


Профиль
Группа: Участник Клуба
Сообщений: 1516
Регистрация: 23.3.2008

Репутация: нет
Всего: 49



Цитата(Нитонисе @  27.8.2012,  13:36 Найти цитируемый пост)

А планировал получить 1 Е-20 


Так Вы его и получили. Я совершенно серьезно: при имеющейся точности операндов этот ответ равен 1E-20.

Цитата(Нитонисе @  27.8.2012,  13:36 Найти цитируемый пост)
Собственно именно так я понимаю точность вычислений. У меня программа выполняет инженерные расчеты. Много возведений в степень, извлечений корней, тригонометрических функций, короче весь математический арсенал используется очень сильно. И вот в результате расчета я получаю некоторые величины. Существует проверка этих величин. Подставляя их в некоторые выражения я должен получить ноль.


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

Так что дело действительно не в типах и библиотеках. Вам надо просто честно получить оценку погрешности вычисляемых результатов, затем - такую же оценку для "нуля" в контрольном критерии, а затем сравнивать получающуюся невязку с нулем с учетом этой оценки. Если разность меньше - все нормально.
PM   Вверх
Нитонисе
Дата 27.8.2012, 13:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 917
Регистрация: 5.11.2009

Репутация: нет
Всего: 2



Цитата(Фантом @  27.8.2012,  12:53 Найти цитируемый пост)
 Вам надо просто честно получить оценку погрешности вычисляемых результатов, затем - такую же оценку для "нуля" в контрольном критерии, а затем сравнивать получающуюся невязку с нулем с учетом этой оценки. Если разность меньше - все нормально.

А как оценить погрешность вычисления? Я-то сейчас просто грубо отсекаю числа меньше 0.001, как равняющиеся нулю. Но иногда такой подход нежелателен, я отсекаю не нули, а просто малые числа. А так бы действительно - сравнивал бы с погрешностью и жилось бы немного лучше smile
PM MAIL   Вверх
Alexeis
Дата 27.8.2012, 13:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

Репутация: 12
Всего: 459



Цитата(Нитонисе @  27.8.2012,  13:15 Найти цитируемый пост)
Да нет, так не будет. Получается что-то типа 0.9999995742 Е-20. 

   Не все десятичные дробные представимы в двоичном виде не периодичной дробью + погрешность вычислений.

Добавлено через 5 минут и 23 секунды
Цитата(Нитонисе @  27.8.2012,  14:35 Найти цитируемый пост)
А как оценить погрешность вычисления? Я-то сейчас просто грубо отсекаю числа меньше 0.001, как равняющиеся нулю.

  Числа с плавающей точкой не сравнивают с нулем, если с ними производились математические операции. Правильнее проверить, что модуль разницы чисел меньше заранее заданной погрешности. Если числа получаются разного порядка, то можно вычислять относительную погрешность. разницу делить на само число и проверять, что погрешность заданное число процентов.


--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
math64
Дата 27.8.2012, 13:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2505
Регистрация: 12.4.2007

Репутация: 8
Всего: 72



При умножении, делении - относительные погрешности складываются.
При сложении и вычитании - складываются абсолютные погрешности.
Т.о. при сложении двух чисел одного знака относительная погрешность сохраняется.
Вычитания чисел одного знака следует избегать, по возможности использовать альтернативные формулы для вычислений.
PM   Вверх
Нитонисе
Дата 27.8.2012, 13:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 917
Регистрация: 5.11.2009

Репутация: нет
Всего: 2



Цитата(Alexeis @  27.8.2012,  13:41 Найти цитируемый пост)
 Числа с плавающей точкой не сравнивают с нулем, если с ними производились математические операции. Правильнее проверить, что модуль разницы чисел меньше заранее заданной погрешности. 

Я так и поступаю. Просто я погрешность задаю жестко 0.001. Наверно это не лучший способ.

Цитата(math64 @  27.8.2012,  13:48 Найти цитируемый пост)
При умножении, делении - относительные погрешности складываются.При сложении и вычитании - складываются абсолютные погрешности.Т.о. при сложении двух чисел одного знака относительная погрешность сохраняется.Вычитания чисел одного знака следует избегать, по возможности использовать альтернативные формулы для вычислений.

А можно пример? А то несовсем понятно.
Код

float a = 1.23456789;
float b = 2.34567891;
float c = a*b + a;

Какова точность вычисления с?
PM MAIL   Вверх
Alexeis
Дата 27.8.2012, 14:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

Репутация: 12
Всего: 459



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

dc = |b * da  + da| + |a * db|; 

Если da = db = eps - машинное эпсилон
Тогда dc = (|b + 1| + |a|) * eps



--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
Нитонисе
Дата 27.8.2012, 14:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 917
Регистрация: 5.11.2009

Репутация: нет
Всего: 2



Цитата(Alexeis @  27.8.2012,  14:13 Найти цитируемый пост)
Если da = db = eps - машинное эпсилон

А что такое машинное эпсилон?
PM MAIL   Вверх
Фантом
Дата 27.8.2012, 14:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Вы это прекратите!
***


Профиль
Группа: Участник Клуба
Сообщений: 1516
Регистрация: 23.3.2008

Репутация: нет
Всего: 49



Цитата(Нитонисе @  27.8.2012,  14:35 Найти цитируемый пост)

А как оценить погрешность вычисления?


Хм... вообще говоря, в двух словах не расскажешь. Есть древняя, но хорошая книга Демидовича и Марона "Основы вычислительной математики", ее легко найти в сети. Скачайте и прочитайте первую главу, это при таких занятиях будет очень полезно.
PM   Вверх
Alexeis
Дата 27.8.2012, 14:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

Репутация: 12
Всего: 459



Цитата(Нитонисе @  27.8.2012,  15:19 Найти цитируемый пост)
А что такое машинное эпсилон? 

http://ru.wikipedia.org/wiki/%D0%9C%D0%B0%...%BE%D0%BB%D1%8C


--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
Нитонисе
Дата 27.8.2012, 15:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 917
Регистрация: 5.11.2009

Репутация: нет
Всего: 2



Цитата(Alexeis @  27.8.2012,  14:13 Найти цитируемый пост)
Тогда dc = (|b + 1| + |a|) * eps

Немного изменю вычисление.
Код

float a = 1.23456789;
float b = 2.34567891;
float c = a + b;

Погрешность вычисления получается dc = (a + b)*eps, где eps = 1E-5.
Точный результат сложения с = 3.5802468.
Погрешность dc = 0.000035802468.
'Это значит, что фактически я могу получить результат сложения с = c +/- dc, так?
Как же ж мне вычислить погрешность, когда у меня таких вчислений тысячи?  smile  параллельно основным вычислениям вести и расчет погрешности?


Цитата(Фантом @  27.8.2012,  14:27 Найти цитируемый пост)
Хм... вообще говоря, в двух словах не расскажешь. Есть древняя, но хорошая книга Демидовича и Марона "Основы вычислительной математики", ее легко найти в сети. Скачайте и прочитайте первую главу, это при таких занятиях будет очень полезно.

Я посмотрел самое начало - как я понял книга предназначена для приближенных ручных вычислений. Думаю приближенный ручной счет и приближенный машинный - не стоит сравнивать.
PM MAIL   Вверх
Alexeis
Дата 27.8.2012, 15:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

Репутация: 12
Всего: 459



Цитата(Нитонисе @  27.8.2012,  16:09 Найти цитируемый пост)
Погрешность вычисления получается dc = (a + b)*eps, где eps = 1E-5.

  Неправильно. в данном случае максимальная погрешность будет 2 * eps . Производная функции y = a + b по а = 1, по b тоже равна 1, поэтому (1 + 1) * eps = 2 * eps .

Цитата(Нитонисе @  27.8.2012,  16:09 Найти цитируемый пост)
Как же ж мне вычислить погрешность, когда у меня таких вчислений тысячи?  smile  параллельно основным вычислениям вести и расчет погрешности?

  Обычно стараются выбрать числа такой точности, чтобы погрешность вычисления была на порядок ниже чем погрешность физических величин. В этом случае ей можно пренебречь. Если используются быстрорастущие функции типа экспонент или обратных тригонометрических, то на некоторых участках функции погрешность может уходить в бесконечность. 

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

  Приведу пример. У меня вычислялась экстраполяция параметра по времени. Для отсчета использовался виндовый высокоточный счетчик. Экстраполяция была квадратичной, поэтому аргумент возведенный в квадрат давал число, которое не влезало в дабл, соответственно младшие разряды красиво отрезались и после операций сложения у меня погрешность улетала в бесконечность. Ситуацию удалось исправить использовав в качестве аргумента не само значение счетчика, а разность между текущим значением и значением в опорной точке. Сразу же значение аргумента уменьшилось на 3-4 порядка, а возведенное в квадрат число стало меньше на 6-8 порядков. 




--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
Нитонисе
Дата 27.8.2012, 15:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 917
Регистрация: 5.11.2009

Репутация: нет
Всего: 2



Цитата(Alexeis @  27.8.2012,  15:44 Найти цитируемый пост)
Перед тем как забивать выражения в компьютер нужно оценивать порядки величин и величины погрешности, которые могут возникать на каждом участке выражения.

Дело в том, что это сложно. По одному и тому же алгоритму могут быть обсчитаны как очень крупные, так и очень малые числа...
PM MAIL   Вверх
math64
Дата 27.8.2012, 15:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2505
Регистрация: 12.4.2007

Репутация: 8
Всего: 72



Можете оценивать точность так:
Код

class Approx {
private:
  double min, max;
public:
  Approx(double _min, double _max) {
    if (_min <= _max) {
      min = _min; max = _max; 
    } else {
      min = _max; max = _min; 
    }
  }
  static Approx fromMinMax(double _min, double _max) {return Approx(_min._max); }
  static Approx fromDelta(double v, double delta) {return Approx(v-delta. v+delta); }
  static Approx fromEps(double v, double eps) {return Approx(v*(1.-eps). v*(1.+eps); }
  operator double () { return (min + max)/2; }
  double delta() { return (max - min)/2; }
  double eps() { return  (max > 0 && min > 0)  || (max < 0 && min < 0) ? (max - min)/(max+min) : DBL_MAX; }
  Approx operator+(Approx n2) {
     return Approx (min+n2.min, max+n2.max);
  }
  // Другие операторы
};


Это сообщение отредактировал(а) math64 - 27.8.2012, 16:02
PM   Вверх
Alexeis
Дата 27.8.2012, 16:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

Репутация: 12
Всего: 459



Цитата(Нитонисе @  27.8.2012,  16:54 Найти цитируемый пост)
Дело в том, что это сложно. 

  Не сомневаюсь. Вероятно, следует использовать использовать различные тесты для проверки таких алгоритмов и делать шаг проверки аргументов экспоненциальным, чтобы охватить проверкой широкий спектр аргументов. Простого способа "сделать все хорошо" я не знаю  smile 


--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
Нитонисе
Дата 27.8.2012, 16:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 917
Регистрация: 5.11.2009

Репутация: нет
Всего: 2



Цитата(math64 @  27.8.2012,  15:57 Найти цитируемый пост)
Можете оценивать точность так:

Покажите на примере c = a + b как воспользоваться вашим классом. 
PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.1110 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.