# Should equality operators be approximate when defining numeric types that rely on floating-point numbers?

For example, say you have a class `Point` which has floating point components. It's tempting to overload the equality operator so you can do something like

``````a = Point(1.1, 2.2)
b = Point(3.3, 6.6)
b /= 3
a == b // should always hold true
``````

This could be achieved through an expression like `abs(a-b) < epsilon`. Is there any particular reason not to do something like this?

• You lose transitivity
Commented Aug 26, 2019 at 4:05
• Now that you mention it, this answer (softwareengineering.stackexchange.com/a/136531/216832) provided a link to these simple slides (accu.org/content/conf2011/…) where the last two mentioned the "roughly equals" operator is intransitive. I for some reason didn't realize the same concept applies to treating == as "roughly equals". Commented Aug 26, 2019 at 4:13

No. Never. Don't. Under any and all Circumstances.

• Not because you could not have a fuzzy equality operation.
• Not because you shouldn't make it easier to work with floats.
• Not because you couldn't overload the operator.

Then why?

Because it won't work...

But heck, let's live dangerously and presume that it will work.

Let's define equality: if two floats are within some `delta` of each other they are equal.

Let's consider these numbers:

``````    A = 2.0000000005
B = 2.0000000000
C = 1.9999999995
D = 1.9999999990
E = 1.9999999985
``````

and assume that delta is:

``````    Delta = 0.0000000005
``````

So:

``````(a)==(b) => absolute(a-b) <= delta;

== | A | B | C | D | E
A | T | T | F | F | F
B | T | T | T | F | F
C | F | T | T | T | F
D | F | F | T | T | T
E | F | F | F | T | T
``````

... that is not equality.

This will work: `A == B && B == C`

This won't work: `B == A && A == C` nor `B == C && C == A`

Try debugging that... what a nightmare. Code that works 1/3 of the time, or alternately works 2/3 of the time depending on what your desired outcome is.

Even worse: `A == B && B == C && C == D && D == E` is the path in which this expression could be true, and it's not even something you would want to hold true `A - E == 0.0000000020` that is four times larger than `delta`.

Not only would this code not work, it would be dreadful to try and debug.

Expectations

Equality is a well defined property. It's transitive, it's commutative, it's reflexive. These qualities provide hugely powerful guarantees. They allow you to substitute one value for another should they compare equal, and many powerful algorithms require that property.

This approximation does not provide those guarantees. Just because they compare equal does not mean that they can be substituted. This will be most apparent with discontinuous functions, where even a small difference can hugely affect the outcome.

If you conflate these two definitions, you are introducing a time bomb bug. Later someone is going to presume that equality means equality, not this approximate equality. They will implement an algorithm that needs the properties equality provides, and it will randomly fail in novel and interesting ways, and worse it will occasionally work for all the wrong reasons.

Define it for what it is

If you need an approximate equality, go ahead and define it. Just define it for what it is.

Something like `similar(a, b)` or if you have access to it `~==` would perhaps work (depending on language conventions).

• This answer is ok (+1), but IMHO just a long-winded way of pointing out a POLA violation. Commented Aug 26, 2019 at 6:10
• But when something seems to be a good idea you may need a long-winded explanation when it's not. Commented Aug 26, 2019 at 7:37
• @DocBrown, Riad's comment on my question was good enough for me to understand why it's a bad idea, but this answer provided exceptional explanation and examples that helped me further understand the repercussions of conflating equals with approximately equals. I definitely welcome long-winded answers that give greater context and help with understanding. Commented Aug 26, 2019 at 18:04
• I do agree with @DocBrown that I could have pointed out the core issue with a single line and then further expounded by example. I was not as clear in the answer as I could have been. Commented Aug 26, 2019 at 23:52