Dims
Dims

Reputation: 51039

Imprecise comparison of complex objects in Java?

It is known, that double values are better if compared imprecisely, with explicit precision (epsilon). For example, two-argument assertEquals(double,double) was deprecated for this reason from jUnit.

But what if we have a compound class, like Matrix, or Vector. How is it recommended to implement a comparison for it? Standard equals() expects only a precise comparison. Is there some convention about this?

Upvotes: 2

Views: 246

Answers (3)

Kevin Krumwiede
Kevin Krumwiede

Reputation: 10298

The best way to compare such objects may differ from one situation to the next. That's why we have the Comparator interface. Instead of embedding the comparison criteria in the class, you can write a Comparator to make the relevant comparison for any given situation.

Upvotes: 0

laazer
laazer

Reputation: 97

Conventionally the equals() method is used to determine if two objects are "equal" as in by the properties of mathematical equality (such as passing the reflexive property and such). If you are using matrices and/or vectors that contain doubles then it is likely that it will be hard to tell whether or not 2 matrices or 2 vectors are reflexive. In this case it might be better to create a method isSimilar() or isAproximatlyEqual()(personally I like the second one because there is no confusion with geometric similarity). By doing this you can allow for a margin of error of some x when comparing 2 doubles and still keep the equals() method for conventional equality. And if you really want to get fancy you can add margin of error as a parameter for these methods.

`
boolean isAproximatlyEqual(double d1, double d2) {
    isAproximatlyEqual(d1, d2, 0.001);
}
boolean isAproximatlyEqual(double d1, double d2, double margin) {
    abs(d1 - d2) < margin;
}
`

Upvotes: 0

Franz D.
Franz D.

Reputation: 1061

A good question, and one without some standard answer (AFAIK), as the problem is not trivial.

First of all, you should read Bruce Dawson's excellent article Comparing Floating Point Numbers, 2012 Edition to get an insight into this surprisingly complex problem. The worst error you can make is to use the infamous abs(a - b) < eps -- don't, it only works for a very limited range of floats and quickly leads to strange bugs! The second-worst error is that you only provide fixed eps values, as the specific values depends very much on your application.

Once you understood the basic problems of float comparisons, the simplest algorithm for a vector comparison would be define two vectors as approximatively equal of each of their corresponding components are approximatively equal (and don't forget to compare the dimensions if they can be different!). However, a better approach would be to check whether the length of the difference vector is approximatively zero.

For matrices, its similar -- consider two matrices approximatively equal if all their corresponding components are approximatively equal. The analogy to the second vector algorithm (difference vector length) could be to check whether the difference matrix determinant is approximatively zero, but this is just a wild hobby-mathematician's guess.

In any case, you should not use a single eps for the approximate comparisons, but let the user specify it, because no eps is good for all applications, regardless of your approximate comparison algorithm. And again: Never use absolute error for approximate float comparisons!

Upvotes: 1

Related Questions