To achieve approx comparison of Double and Float values, I have override the fixture class as the following:
public class ApproxColumnFixture extends ColumnFixture {
@Override
public void check(Parse cell, TypeAdapter a) {
if (a.type == Double.class) {
super.check(cell, new ApproxDoubleAdapter(a));
} else if (a.type == Float.class) {
super.check(cell, new ApproxFloatAdapter(a));
} else {
super.check(cell, a);
}
}
}
The two TypeAdapter class use both relative value epsilon and absolute value precision for comparison. The precision is detected from the expected input, so that 23.099 has precision 0.001. They also expect special values, such as "nan" for NaN, and "inf" for +/-Infinitive. Here is one example:
public class ApproxDoubleAdapter extends TypeAdapter {
public final Double ZERO = new Double(0.0);
private final double epsilon;
private int precisions = -1;
public ApproxDoubleAdapter(final TypeAdapter classDoubleAdapter, double epsilon) {
this.target = classDoubleAdapter.target;
this.fixture = classDoubleAdapter.fixture;
this.field = classDoubleAdapter.field;
this.method = classDoubleAdapter.method;
this.type = classDoubleAdapter.type;
this.isRegex = classDoubleAdapter.isRegex;
this.epsilon = epsilon;
}
public ApproxDoubleAdapter(final TypeAdapter adapt) {
this(adapt, 0.0001);
}
public Object parse(String s) throws Exception {
if ((s == null) || s.equals("null")) {
return null;
}
if (s.equals("0")) {
return ZERO;
}
if (s.equals("nan")) {
return Double.NaN;
}
if (s.equals("inf")) {
return Double.POSITIVE_INFINITY;
}
precisions = s.indexOf(".");
if (precisions >= 0) {
precisions = s.length() - 1 - precisions;
}
return new Double( Double.parseDouble(s) );
}
public boolean equals(Object a, Object b) {
if (a == null) {
return (b == null);
}
if (b == null) {
return (a == null);
}
if ((a.getClass() != Double.class) || (b.getClass() != Double.class)) {
return false;
}
double aV = (Double) a;
double bV = (Double) b;
if (Double.isNaN(aV)) {
return Double.isNaN(bV);
}
if (Double.isNaN(bV)) {
return Double.isNaN(aV);
}
if (Double.isNaN(aV)) {
return Double.isNaN(bV);
}
if (Double.isInfinite(aV)) {
return Double.isInfinite(bV);
}
if (Double.isInfinite(bV)) {
return Double.isInfinite(aV);
}
final double diff = Math.abs(aV - bV);
if (diff <= Math.abs(aV + bV) * epsilon) {
return true;
}
if (precisions > 0) {
return diff <= Math.pow(10, precisions);
} else if (aV == 0.0) {
return diff < epsilon;
} else {
return false;
}
}
}