2016-02-08 2 views
0

У меня есть два вектора:Проверяется два вектора равны

std::vector<double> calculatedValues = calculateValues(); 
std::vector<double> expectedValues = {1.1, 1.2}; 

Я использую cpputest, чтобы проверить, если эти векторы равны:

CHECK_TRUE(calculatedValues == expectedValues) 

Это работает. Тем не менее, мне интересно, не следует ли использовать некоторый допуск, потому что я все-таки сравниваю удваивает.

+8

Я не думаю, что мы сможем ответить на этот вопрос для вас, не зная, что требования вашей программы. – ApproachingDarknessFish

+2

Этот вопрос действительно не похож на 'vector'; что кажется случайным. Это больше о плавающей точке, эпсилон и т. Д. - все обычные подозреваемые, подробно обсуждаемые во многих других потоках. ;-) После того, как вы определились с выбранным вами методом/допуском, вы сможете предоставить пользовательскую функцию компаратора или, возможно, даже перегрузить (свободный или встроенный) 'operator ==' для вашего вектора и выполнить итеративное сравнение, используя собственный компаратор. –

+0

Нельзя просто выбросить эпсилон и ожидать удовлетворительного решения - для некоторых целей требуется точное равенство (проверка детерминированных вычислительных алгоритмов), для других может потребоваться равенство трех знаков после запятой (например, satnav, 1 метр для прибытие в пункт назначения в автомобиле) в CAD/CAM, где разумные понятия равенства зависят от точности, которую вы хотите/на машине. Итог: вам нужно подумать о модели, которую вы моделируете, и о том, что считается «равным» в этой системе, и перевести эту концепцию в свою программу. – Ben

ответ

2

Для сравнения значений с плавающей точкой, вы должны сделать что-то вроде этого:

bool is_equal(double a, double b) { 

    return (abs(a-b)/b < 0.0001); // 0.00001 value can be a relative value 
} 

Вы можете адаптировать его сравнить свои векторы.

+0

Значение 0,000001 должно быть относительным! – Radek

1

Да, вы должны использовать некоторый допуск, поскольку операции с плавающей запятой не гарантируют получение одинаковых результатов на разных ЦП. Может быть, например, ошибки округления.

Однако стандарты SSE/SSE2 предоставляют воспроизводимую математику с плавающей запятой, поэтому вы можете рассмотреть возможность использования флага компиляции/ARCH: SSE2 в качестве альтернативы. Тем не менее, трудно гарантировать, что никакая математика x87 не используется в любом месте приложения, поэтому будьте осторожны!

0

Вместо operator== вы можете использовать std::equal() с пользовательскими эпсилоном:

bool equal = std::equal(calculatedValues.begin(), calculatedValues.end(), expectedValues.begin(), 
         [](double value1, double value2) 
         { 
          constexpr double epsilon = 0.01; // Choose whatever you need here 
          return std::fabs(value1 - value2) < epsilon; 
         }); 
CHECK_TRUE(equal); 
Смежные вопросы