3 ms·
> Testing for absolute error is often incorrect True, but in this case it was to test for near-zero values so absolute error comparison is good enough. Here's
by exDM69 11y ago
> Testing for absolute error is often incorrect
True, but in this case it was to test for near-zero values so absolute error comparison is good enough.
Here's a few macros I have been using to compare floating point values for approximate equality. It should be true if the values are equal to about 6-7 decimal places (in base-10). I use this in testing some code that deals with algorithms that have known numerical precision issues. The errors are inherent to the algorithms, not specifically floating point errors (e.g. solving Kepler's equation for near-parabolic trajectories).
Note that it isn't specified whether "a" or "b" is the "gold" value to compare against, so it's measuring the relative error against a rough average of the two magnitudes.
#define ZEROF(x) ((x)*(x) < DBL_EPSILON)
#define EQF(a, b) ((ZEROF(a) && ZEROF(b)) || \
ZEROF(((a)-(b))*((a)-(b))/((a)*(a) + ((b)*(b)))))
I am no scientist, so if anyone has improvement to the code above, I'll gladly take any feedback.
- stinos 11y agobut in this case it was to test for near-zero values so absolute error comparison is good enough Unless you are working with small numbers? Suppose you are dividing 1e-30 by 1e-30 than the result should still be 1 so if you return 0 when the second argument is < 1e-6 then you're screwed. I think boost's close_at_tolerance does what your macro tries to do; basically you say 'here's two numbers, check if their values differ no more than x% of their value' With the advantage that it is not a macro and guards against overflow etc: http://www.boost.org/doc/libs/1_37_0/boost/test/floating_point_comparison.hpp http://www.boost.org/doc/libs/1_37_0/boost/test/floating_poi....
- exDM69 11y ago> Unless you are working with small numbers? Suppose you are dividing 1e-30 by 1e-30 than the result should still be 1 so if you return 0 when the second argument is < 1e-6 then you're screwed. A very good point which I didn't think of! Obviously the 1e-6 figure is specific to the application. How should one avoid division by zero then? You can't figure out the relative error without a division, can you? For normal comparisons, using a relative error is the way to go but the zero case is different. On the other hand, using quantities of magnitudes in 1e-30 is already using half the exponent, a change of units may be due here.
- stinos 11y agoHow should one avoid division by zero then? Good question and in this case I really can't tell, it depends on the problem domain (i.e. is your normal data set numbers greater than 1 or rather smaller then 1e-100) and I'm not sure if is possible (in a feasible way) to write one generic function which works for all cases.