0

I'm trying to compare two class objects, which has both been initialized with 0.0, but for some reason C++ decides to convert the 0.0 to some extremly small value instead of keeping the 0.0, which makes the comparison fail as the value it converts to is not always exactly the same.

Vector.cpp

#include "Vector.h"

// operator overloadings
bool Vector::operator==(const Vector &rhs) const
{
  return x == rhs.x && y == rhs.y;
}

bool Vector::operator!=(const Vector &rhs) const
{
  return x != rhs.x || y != rhs.y;
}

Vector.h

#pragma once
class Vector
{

private:
  double x;
  double y;

public:
  // constructor
  Vector(double x = 0.0, double y = 0.0){};

  // operator overloading
  bool operator==(const Vector &rhs) const;
  bool operator!=(const Vector &rhs) const;
};

main.cpp

#include "Vector.h"
#include <cassert>

using namespace std;
int main()
{
  Vector zero{};

  // check default constructor
  assert((Vector{0.0, 0.0} == zero));

What is going on here and how should it be rewritten?

I'm using the clang compiler if it makes any difference.

1 Answers1

4

Your Vector class never initializes the x and y members.

Since the member variables are uninitialized, they will have an indeterminate value, which you should look at like it was random or garbage. Using indeterminate values of any kind in any way, leads to undefined behavior.

To initialize the member variables, use a constructor initializer list:

Vector(double x = 0.0, double y = 0.0)
    : x{ x }, y{ y }
{
}

On another note, floating point arithmetic on a computer will lead to rounding errors. The more operations you perform, the larger the error will be. And sooner or later you will think that floating point math is broken.

All this rounding of course means that it's almost impossible to do exact comparisons of floating point values.

The common way is to use an epsilon, a small margin of error, for your comparisons.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • 1
    **Sidenote:** though knowing the caveats is important, I do not like the mantra about floating point operations. Doing exact comparisons is fine and I have worked on several projets that do that. You have to know what you compare and why, and picking "exact" is as valid an outcome as picking "10^-3" or "10^+7" as ε. It entirely depends on what you do, and the api for a Vector should provide a way to let the caller specify that value - including 0. – spectras Aug 15 '22 at 11:42