Разница между BOOST_CHECK_CLOSE и BOOST_CHECK_CLOSE_FRACTION?

Может ли кто-нибудь описать разницу в поведении между BOOST_CHECK_CLOSE и BOOST_CHECK_CLOSE_FRACTION? В документации подразумевается, что оба макроса обрабатывают свой третий параметр одинаково, что заставляет меня подозревать, что документация неверна.

В частности, BOOST_CHECK_CLOSE_FRACTION дает мне некоторые нечетные результаты:

error in "...": difference between *expected{0} and *actual{-1.7763568394002506e-16} exceeds 9.9999999999999995e-07

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

Ответы

Ответ 1

В соответствии с это обсуждение, один (BOOST_CHECK_CLOSE) рассматривает третий параметр как выражение процента, тогда как другой (BOOST_CHECK_CLOSE_FRACTION) рассматривает его как выражение фракции. Итак,.01 в первом должен быть эквивалентен .0001 во втором.

Не уверен, что это объясняет вашу проблему - вы получаете тот же нечетный результат с BOOST_CHECK_CLOSE? Я бы не был шокирован, если 0 вызвал проблему, но у меня нет первого опыта работы с макросами.

Ответ 2

Да. Zero не является "близким" к любому значению. Вместо этого вы можете использовать BOOST_CHECK_SMALL.

Ответ 3

@Gennadiy: Zero может быть близким к любому небольшому значению.:-) Относительные различия растут произвольно большими, если ожидаемое значение очень близко к нулю.

Вот обходная функция, которую я использую для unit-test double values: если ожидаемое значение очень мало или равно нулю, я проверяю малость наблюдаемого значения, в противном случае проверяю близость:

void dbl_check_close(
    double expected, double observed, 
    double small, double pct_tol
) {
    if (std::fabs(expected) < small) {
        BOOST_CHECK_SMALL(observed, small);
    } else {
        BOOST_CHECK_CLOSE(expected, observed, pct_tol);
    }
}

Конечно, было бы здорово создать макрос BOOST_CHECK_SMALL_OR_CLOSE, который сделает это автоматически. Геннадий мог бы поговорить с автором Boost.Test; -)