I have some numbers I'm trying to compare. They represent lengths of paths through different spaces.
Unfortunately for me, some imprecision was causing false comparisons. For instance, after noting the wrong effects, I found that I was having comparisons like this:
a = 384.527100541296
b = 384.52710054129614 // Note the trailing 14
For my purposes, a and b are supposed to be equal.
I noted the guava has a fuzzyCompare()
method for doubles which seems to do what I want in ignoring some of this precision:
private static final double COMPARISON_PRECISION=1e-10;
private static final Comparator<Double> fuzzyCompare= new Comparator<Double>(){
public int compare(Double o1, Double o2) {
return DoubleMath.fuzzyCompare(o1, o2, COMPARISON_PRECISION);
}
};
public int compareTo(Object o) {
if (o instanceof Spam) {
Spam other = (Spam) (o);
return ComparisonChain.start()
.compare(this.getLength(),other.getLength(),fuzzyCompare)
//...
.result();
} else {
throw new ClassCastException();
}
}
The warning on that fuzzy compare did not slip my notice:
This is not a total ordering and is not suitable for use in Comparable.compareTo(T) implementations. In particular, it is not transitive
My question is, is this lack of transitivity a real problem? If it is, how would it present itself? I would think that if the comparison were really truly violated it would throw an error similar to this question: Java error: Comparison method violates its general contract, and its not doing that even against a variety of values I've tested.
Or perhaps since an IllegalArgumentException
is a runtime error, I just haven't run across the problems yet because only some devious values will trigger the problem?
Or perhaps it is doing something wrong right now, it just subtle enough that I haven't noticed it?
List<T>
to be sorted, whetherCollection.sort(List<T>, Comparator<T>)
will throw the Java error: Comparison method violates its general contract or not. – Commutable