2014 dxdy logo

Научный форум dxdy

Математика, Физика, Computer Science, Machine Learning, LaTeX, Механика и Техника, Химия,
Биология и Медицина, Экономика и Финансовая Математика, Гуманитарные науки




Начать новую тему Ответить на тему
 
 сравнение double в c++
Сообщение12.12.2011, 10:48 


02/11/11
124
В файле float.h находится константа DBL_EPSILON, которая равна минимальному x такому, что 1.0 + x > x. И далее везде в интернетах утверждается, что для сравнения на равенство чисел a и b достаточно написать
Используется синтаксис C++
if (fabs(a-b) <= DBL_EPSILON*fmax(fabs(a), fabs(b))) {
  // a == b с относительной точностью DBL_EPSILON
}
 


Почему это так? Откуда такое неравенство?

 Профиль  
                  
 
 Re: сравнение double в c++
Сообщение12.12.2011, 14:20 
Заслуженный участник
Аватара пользователя


01/08/06
3131
Уфа
На самом деле вопрос сравнения чисел с плавающей точкой, увы, не прост.
Ошибки округления могут накапливаться, и нужно их как-то оценивать.
Если в Вашем примере a и b имеют тип float или double (и отключена оптимизация, позволяющая хранить промежуточные результаты в регистрах), то проще будет написать (a == b) — результат будет тот же (хотя насчёт double я не совсем уверен, но практический смысл расписывать "длинный" способ отсутствует).
Вообще, "длинный" способ, конечно, корректнее, но тут нужно:
1) подобрать правильное EPSILON;
2) отдельно рассмотреть случай, когда числа a и b близки к нулю.
Оба пункта нужно рассматривать исходя из практических соображений, которые в каждом случае разные.
Например, я в одной из расчётных программ использовал примерно такую функцию:
Используется синтаксис C
bool areEqual(double x, double y)
{
  static double SMALL_NUM = 1.0E-5;
  if (abs(x) < SMALL_NUM && abs(y) < SMALL_NUM)
    return abs(x-y) < SMALL_NUM;
  else
    return abs(x-y) < abs(x) * SMALL_NUM;
}
Всё работало отлично, пока не пришлось работать с физическими величинами в мелком масштабе (порядок величины в единицах СИ — $10^{-6}$). Такие переменные пришлось сравнивать с нулём по-другому :-(

 Профиль  
                  
 
 Re: сравнение double в c++
Сообщение12.12.2011, 14:34 
Заслуженный участник
Аватара пользователя


30/01/06
72407
Относительная погрешность $\varepsilon$ и абсолютная погрешность $\Delta$ при известной величине $v$ связаны между собой как $\varepsilon=\Delta/v,$ $\Delta=\varepsilon v.$

Так что, когда вам надо найти, что числа равны с заданной погрешностью, $\lvert a-b\rvert\leqslant\Delta,$ то вы оцениваете $\Delta=\max\{\Delta_a,\Delta_b\},$ где $\Delta_a=\varepsilon a,$ $\Delta_b=\varepsilon b.$

В принципе, выбор наибольшей $\Delta$ - стандартная процедура - в данном случае перестраховка, поскольку если две величины будут различаться по порядку величины, то и между собой они равны не будут. С другой стороны, она обеспечивает хотя бы коммутативность отношения: $a\approx b\Leftrightarrow b\approx a,$ хотя уже ни о какой транзитивности речь не идёт.

И совет на будущее: никогда не полагайтесь на сравнения с погрешностью DBL_EPSILON. Если у вас есть два числа, которые надо сравнить, то они откуда-то происходят, из каких-то измерений или расчётов, и их погрешность всегда выше, чем DBL_EPSILON. Правильно в таком случае использовать погрешность вычислений или измерений, которую вы оцениваете или сами, или требуете от того, кто предоставляет вам сами числа.

 Профиль  
                  
 
 Re: сравнение double в c++
Сообщение12.12.2011, 18:05 


01/07/08
836
Киев
max(Im) в сообщении #514633 писал(а):
которая равна минимальному x такому, что 1.0 + x > x

точнее должно быть x>0, а далее по вашему тексту. Константы такие машинно-зависимые. В CBuilder6 их 3 для разных типов чисел с плавающей запятой.
Код:
#define DBL_EPSILON         2.2204460492503131E-16
#define FLT_EPSILON         1.19209290E-07F
#define LDBL_EPSILON        1.084202172485504434e-019L


max(Im) в сообщении #514633 писал(а):
Почему это так?

Это связано со стремлением достичь минимальной по абсолютному значению относительной погрешности для разных типов чисел с плавающей запятой и разных по величине чисел. С уважением,

 Профиль  
                  
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 4 ] 

Модераторы: Karan, Toucan, PAV, maxal, Супермодераторы



Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group