Compare Vector of Doubles Using Catch
Asked Answered
S

3

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.

Speck answered 25/1, 2017 at 23:21 Comment(2)
What about looping over the vectors and comparing element-wise? See also this question.Cleome
@vso I think the issue is not how to loop over a vector, but how to compare floating-point numbers while doing so.Cultigen
C
7

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.

Connoisseur answered 17/6, 2021 at 22:10 Comment(0)
S
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.

Speck answered 3/2, 2017 at 17:15 Comment(1)
I am facing the very same problem and I am interesting in a more elegant solution.Negotiation
D
1

An alternative to the other answers are the Range and Vector matchers.

For example, two vectors of ints can be compared like so:

#include <catch2/catch_test_macros.hpp>
#include <catch2/matchers/catch_matchers.hpp>
#include <catch2/matchers/catch_matchers_vector.hpp>

std::vector<int64_t> result = func();
std::vector<int64_t> expected = {3306, 267, 1002, 256};
REQUIRE_THAT(result, Catch::Matchers::Equals(expected));
Dyadic answered 7/5 at 6:48 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.