5

I'm using the Catch unit testing framework, and I'd like to compare a vector of doubles. This other answer suggests using Approx to compare floating point/double values, but this doesn't work for a vector of them. Is there any convenient way of accomplishing this?

EDIT: An Example

With the following code:

#define CATCH_CONFIG_MAIN
#include "catch.hpp"

TEST_CASE("Compare Vectors", "[vector]") {
    std::vector<int> vec1 = {0, 1, 2, 3};
    std::vector<int> vec2 = {0, 1, 2, 4};
    REQUIRE(vec1 == vec2);
}

The test fails with following report:

-------------------------------------------------------------------------------
Compare Vectors
-------------------------------------------------------------------------------
test/UnitTests/test_Example/example.cc:4
...............................................................................

test/UnitTests/test_Example/example.cc:7: FAILED:
  REQUIRE( vec1 == vec2 )
with expansion:
  { 0, 1, 2, 3 } == { 0, 1, 2, 4 }

===============================================================================
test cases: 1 | 1 failed
assertions: 1 | 1 failed

But if I change the code as follows, I would want the test to pass, but obviously it doesn't.

#define CATCH_CONFIG_MAIN
#include "catch.hpp"

TEST_CASE("Compare Vectors", "[vector]") {
    std::vector<double> vec1 = {0, 1, 2, 3};
    std::vector<double> vec2 = {0, 1, 2, 3.000001};
    REQUIRE(vec1 == vec2);
}

I could loop through the elements and compare them one-by-one, but in the event of a discrepancy, it will be more difficult to determine the source of the error.

  • 1
    What about looping over the vectors and comparing element-wise? See also [this question](http://stackoverflow.com/q/41160846/3093378). – vsoftco Jan 25 '17 at 23:26
  • @vso I think the issue is not how to loop over a vector, but how to compare floating-point numbers while doing so. –  Jan 25 '17 at 23:32

2 Answers2

5

Although it has been ~4 years, since Catch 2.7.2, users can now compare vectors using Approx:

REQUIRE_THAT(vec1, Catch::Approx(vec2).margin(0.0001));

That would compare the two vectors within +- 0.0001 of error. More details here.

Dávid Tóth
  • 2,788
  • 1
  • 21
  • 46
gvegayon
  • 812
  • 12
  • 23
2

For the time being I've resorted to a kind of workaround. I created the following two functions to be used wherever you want to check two vectors. (i.e. REQUIRE(compareVectors(vec1, vec2)); )

bool compareVectors(std::vector<double> a, std::vector<double> b) {
    if (a.size() != b.size()) return false;
    for (size_t i = 0; i < a.size(); i++) {
        if (a[i] != Approx(b[i])) {
            std::cout << a[i] << " Should == " << b[i] << std::endl;
            return false;
        }
    }
    return true;
}

bool compare2dVectors(std::vector<std::vector<double>> a,
                      std::vector<std::vector<double>> b) {
    if (a.size() != b.size()) return false;
    for (size_t i = 0; i < a.size(); i++) {
        if (! compareVectors(a[i], b[i])) return false;
    }
    return true;
}

That way you'll at least be able to see the name of the vector that failed, and the first values that differed.

It's not the ideal solution, so I'm still hoping someone will be able to come up with something better, but I thought I'd at least share what I've come up with so far in case it helps somebody.