Как сравнить float и double?

118
20 мая 2019, 07:40

Как правильно сравнивать два числа типа float и double? Следующий способ часто говорит, что одинаковые числа различны:

float a = 0.00001001;
double b = 0.00001001;
if (a == b) {
  std::cout << "equal"; // не выводит equal
}

Мой вопрос отличается от дубликатов тем, что мне нужно знать, как правильно сравнить 2 числа типа float и double на C++, а не почему (не только почему) простое сравнение не работает. В привидённых в дубликатах ответах либо ответы для 2 одинаковых типов, либо не сказано как выбирать epsilon и т.д..

Answer 1
if (fabs(a - b) <= eps)

где eps - некая маленькая величина, вообще говоря - зависящая от порядка самих чисел, поэтому более корректно

if (fabs(a - b)/ max(fabs(a) + eps, fabs(b) + eps) <= eps)

Пример задания eps:

const
  FuzzFactor = 1000;
  SingleResolutionEps = 1E-7 * FuzzFactor;
  DoubleResolutionEps = 1E-15 * FuzzFactor;

Откуда это берётся - точность float 23 двоичных разряда или 7-8 десятичных, т.е. число имеет 7 верных десятичных цифр, поэтому меньше 1E-7 eps смысла нет делать.

Почему используется множитель FuzzFactor = 1000; - это расширение допуска, чёткого критерия его выбора нет, разработчики этой библиотеки решили так сделать, а вообще множитель можно выбирать в зависимости от желаемой погрешности в младших разрядах.

Для сравнения float и double по правилам сложения погрешностей следует использовать погрешность для менее точных float, т.е. порядка 1E-7 даже при приведении float к double, как предложил в комментарии @Grundy - ведь при этом приведении возникают дополнительные ничем не обеспеченные разряды с погрешностью в пределах всё тех же 1E-7.

Труды по точности float-арифметики: 1 2 Goldberg

Answer 2

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

А машинный эпсилон это характеристика данной вычислительной системы.

READ ALSO
property в GNU Compiler Collection

property в GNU Compiler Collection

Есть ли в GCC аналог microsoft'овских property https://msdnmicrosoft

150
Сделать выделение рамки на изображении, Android

Сделать выделение рамки на изображении, Android

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

147
Настройка Swagger в приложении на Spring Boot

Настройка Swagger в приложении на Spring Boot

Хочу настроить swagger для документирования REST-сервиса на spring bootСледую гайду на этом сайте

168