2014-02-19 3 views
3

После прохождения нескольких статей здесь и при поиске есть много хороших решений для сравнения чисел с плавающей запятой.Использование Boost Floating Point Сравнение для получения возвращаемого значения bool

Такие, как библиотека Boost,: http://www.boost.org/doc/libs/1_34_0/libs/test/doc/components/test_tools/floating_point_comparison.html

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

Например, они показывают примеры, как так: http://www.boost.org/doc/libs/1_50_0/libs/test/doc/html/utf/testing-tools/reference.html

Но это не возвращает логическое значение.

псевдопользователей пример кода:

double a = 1.0; 
double b = 0.5+0.5; 
double percentage = 0.00001; //0.001 % 
//Now I want to use the boost library to do something like this: 
bool isClose = check_is_close(a, b, percentage); 

Я просто возникли проблемы с поиском, как получить логическое значение обратно.

Я работал в основном на Java, Python и Matlab в течение нескольких лет, поэтому C++ для меня сейчас как иностранный.

Пожалуйста, помогите!

ответ

1

Вы должны понимать, что то, на что вы указали, являются вспомогательными инструментами для тестирования блока boost, поэтому, возможно, не стоит полагаться на него вне домена тестирования.

А в качестве побочного примечания во многих случаях достаточно просто сравнить числа с плавающей запятой в пределах эпсилона абсолютного расстояния (например, 1е-6). В противном случае, конечно, необходимо относительное расстояние относительно величины сопоставлений - когда требуется более высокая точность.

Но это не возвращает булево

Да она возвращает boost::test_tools::predicate_result, но вы можете оценить и преобразовать его в логическое значение.

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

#include <iostream> 
#include <boost/test/floating_point_comparison.hpp> 

int main() { 
    bool b = boost::test_tools::check_is_close(
     0.01, 0.015, boost::test_tools::percent_tolerance(49.0)); 
    std::cout << std::boolalpha << b << std::endl; // false 

    b = boost::test_tools::check_is_close(
     0.01, 0.015, boost::test_tools::percent_tolerance(51.0)); 
    std::cout << std::boolalpha << b << std::endl; // true, 51% tolerance is enough to ignore the difference 
} 

И если вам необходимо реализовать простое сравнение, вы всегда можете свернуть свой собственный, вдоль линий:

#include <cmath> 
bool is_close(double a, double b, double epsilon = 1e-5) { 
    return std::fabs(a - b) < epsilon; 
} 
+0

(редактирование: Извините за формат, двойное пространство не вставить разрыв строки) Спасибо, я так близко; Я не подбирал тип персетов и пытался передать его как двойник. Во втором примере, я нашел лучшее уравнение в моих поисках: BOOL isEqualDouble (двойной а, б) дважды { статических двойного DBL_EPSILON = STD :: numeric_limits :: эпсилон(); return fabs (a - b) <= 16 * DBL_EPSILON * fmax (fabs (a), fabs (b)); } – user3325798

+0

@ user3325798 Повторите второй пример - это будет правильно, но в значительной степени, только если вам нужна эта значительная точность сравнения (она находится вокруг | a, b | * 2e-1000). Вот почему я использовал в своем ответе как 1е-6, так и 1е-5, ​​чтобы показать, что вам нужно определить точность между возможными точками, которые подходят вашему делу. – mockinterface

+0

Примечание: это больше не работает с Boost 1.59. Мне пришлось использовать 'boost :: math :: fpc :: percent_tolerance'. – BenC

1

может быть сделано без каких-либо зависимостей библиотеки/заголовка:

inline bool is_close(double a, double b, double tolerance = 1e-5) 
{ 
    return (a - b) * (a - b) < tolerance * tolerance; 
} 

Вот как я делаю это за пределами тестового домена. Он легкий и эффективный, а также простой в использовании и использовании.Ответ

1

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

template <typename Number> 
inline boost::test_tools::predicate_result isClose(Number a, Number b, Number tolerance = Number(1e-5)) 
{ 
    if ((a-b)*(a-b) < tolerance*tolerance) 
    { 
     return true; 
    } 

    boost::test_tools::predicate_result result(false); 
    result.message() << a << " != " << b << " within " << tolerance; 
    return result; 
}