Как сравнить две вещественные переменные в C++?

«Как сравнить две вещественные переменные в C++?» — вопрос из категории C++ Core, который задают на 25% собеседований C/C++ Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Прямое сравнение вещественных чисел через == ненадежно из-за ошибок округления при представлении в памяти. Стандартный подход — сравнение с допустимой абсолютной погрешностью (epsilon).

#include <cmath>

bool almostEqual(double a, double b, double epsilon = 1e-9) {
    return std::fabs(a - b) < epsilon;
}

Почему этого может быть недостаточно? Абсолютный epsilon плохо работает для чисел разного масштаба (например, сравнение 1e-10 и 2e-10). В таких случаях используют относительную погрешность.

bool relativeEqual(double a, double b, double relEpsilon = 1e-9) {
    double maxVal = std::max(std::fabs(a), std::fabs(b));
    // Защита от деления на ноль при сравнении с нулём
    if (maxVal < relEpsilon) return true;
    return std::fabs(a - b) / maxVal < relEpsilon;
}

Практические советы:

  • Для финансовых расчётов используйте целочисленные типы (счёт в копейках/центах) или библиотеки с десятичной арифметикой.
  • В C++11 появились std::nextafter и std::nexttoward для сравнения с учётом соседних представимых чисел.
  • Библиотеки вроде Google Test (ASSERT_NEAR, ASSERT_DOUBLE_EQ) реализуют комбинированный подход (Ульп-тест), проверяющий и абсолютную, и относительную разницу.