Thanks for your answers.
As I said, our solution first uses equals() method, to distinguish wether number are "strictly"
equals (thanks to existing methods) before dividing the difference by the max value of (x,y).
So I tested the use case proposed by Luc with our implementation and with Luc's one (see here
after).
About the default value (1e14), I know the tolerance is casedependant, but some times, we
don't precisely know the order of magnitude (ex : jacobians matrices) and it's quite practical
to have a default value.
In our tools, we use this value in the test classes, but also for specific algorithm convergence
threshold.
If you agree, I'll open a ticket and attach our patch.
Best regards,
Yannick

Here are the results obtained with various methods : CommonsMath equals (one ulp), our method
with a relative 1e14 threshold, and another method (abs(x1x2) <= eps * max(abs(x1),abs(x2)
)

X: 0.0 vs Y: 0.0
Equals (CM) true
EqualsWithRelativeTol true
EqualsOtherSolution false

X: 0.1 vs Y: 0.1000000000001
Equals (CM) false
EqualsWithRelativeTol false
EqualsOtherSolution false

X: 1.7976931348623157E308 vs Y: 1.7976931348623157E308
Equals (CM) true
EqualsWithRelativeTol true
EqualsOtherSolution true

X: 4.9E324 vs Y: 4.9E324
Equals (CM) true
EqualsWithRelativeTol true
EqualsOtherSolution false

X: Infinity vs Y: Infinity
Equals (CM) true
EqualsWithRelativeTol true
EqualsOtherSolution false

X: NaN vs Y: NaN
Equals (CM) false
EqualsWithRelativeTol false
EqualsOtherSolution false

X: 0.0 vs Y: 0.0
Equals (CM) true
EqualsWithRelativeTol true
EqualsOtherSolution false

X: Infinity vs Y: Infinity
Equals (CM) true
EqualsWithRelativeTol true
EqualsOtherSolution false

X: 0.100000000000001 vs Y: 0.1
Equals (CM) false
EqualsWithRelativeTol true
EqualsOtherSolution true

X: 0.1000000000000011 vs Y: 0.1
Equals (CM) false
EqualsWithRelativeTol false
EqualsOtherSolution false
Message d'origine
De : Gilles Sadowski [mailto:gilles@harfang.homelinux.org]
Envoyé : mercredi 19 septembre 2012 16:38
À : dev@commons.apache.org
Objet : Re: [math] Adding some methods in Precision class (oacm.util)
Hi.
>
> >
> > This message is about some methods in Precision class, and follows a
> > discussion about MATH863
> > (https://issues.apache.org/jira/browse/MATH863).
> >
> > Recently, we slightly modified our Precision class, by adding a
> > specific epsilon value to compute a relative deviation and also some
> > methods.  /** Epsilon used for doubles relative comparison */
> > public static final double DOUBLE_COMPARISON_EPSILON = 1.0e14; 
> >
> > This value is quite useful to compare two values. It's
> > approximatively 100 times larger than the previous EPSILON value
> > (1e16, the difference between 1. and the next closest value).
> >
> > We also added static methods, to compute a relative difference : if
> > x1 and x2 are not equal (according to the equals(x1,x2, "1 ulp")
> > function), then we compute a relative deviation
> > ("abs(x1x2)/max(abs(x1),abs(x2))" and see if it's lower than an
> > epsilon value.
>
> The comparison should probably rather be:
> abs(x1x2) <= eps * max(abs(x1),abs(x2)
>
> The reason for that is that with your implementation when both x1 and x2
> are 0 (either +0 or 0), then the result would be false, despite the
> numbers are equal. The division 0/0 leads to a NaN and all comparisons
> involving NaN return false.
Unfotunately, that version makes the comparison fail when one of the
argument is infinite; in that case we get for the proposed code
inf / inf < eps > false thanks to NaN
while the above leads to
inf <= inf > true
Also, the proposed implementation first checks for strict equality: when the
arguments are equal, the division is not performed.
[I wanted to replace the proposed implementation with a call to the existing
"absolute" comparison method, but because of that problem, it doesn't seem
possible without adding conditionals.]
> >
> >  public static boolean equalsWithRelativeTolerance(final double x,
> > final double y) > uses the DOUBLE_COMPARISON_EPSILON public static
> > boolean equalsWithRelativeTolerance(final double x, final double y,
> > final double eps) 
> >
> > These kind of methods are used in some of our tools (space dynamic
> > libraries) to assert equality between values, when we don't know the
> > order of magnitude.
> >
> > Do you think it's useful for Commons Math users ? Shall I open a
> > ticket on JIRA and contribute the corresponding code source ?
>
> Yes, along with test cases, including special cases (+/0, +/infinity,
> NaNs, +/Double.MAX_VALUE, +/Double.MIN_VALUE ...)
I think that we should focus on the second version (with an explicit
tolerance).
The tolerance is very much casedependent, so that the default value is not
widely useful: Why 1e14 rather than 1e15 or 1e13 or even 1e7 ?
Best regards,
Gilles

To unsubscribe, email: devunsubscribe@commons.apache.org
For additional commands, email: devhelp@commons.apache.org

To unsubscribe, email: devunsubscribe@commons.apache.org
For additional commands, email: devhelp@commons.apache.org
