[Qt-interest] strange qFuzzyCompare implementation

Stephan Rose kermos at somrek.net
Mon Apr 13 14:13:29 CEST 2009


On Mon, 2009-04-13 at 08:46 +0200, Konrad Rosenbaum wrote:
> On Monday 13 April 2009, Stephan Rose wrote:
> > There actually is another way to do a float compare like this that does
> > *not* rely on that type of hardcoded value.
> >
> > #define MaxError 5
> 
> But it relies on another type of hardcoded value.
> 
> > bool compareFloat(float p1, float p2)
> > {
> >   int a, b;
> >   memcpy(&a, &p1, sizeof(float));
> >   memcpy(&b, &p2, sizeof(float));
> >
> >   a = a < 0 ? 0x80000000 - a : a;
> >   b = b < 0 ? 0x80000000 - b : b;
> >
> >   return qabs(a - b) <= MaxError;
> > }
> 
> Your algorithm compares the absolutes of two numbers instead of the two 
> numbers and I'm not entirely sure whether its behaviour for negative 
> numbers is what you intended (floats encode the absolute plus sign, whereas 
> ints encode negatives as inverted bits).
> 
> I think your conversion of negatives should be
> 
> a &= 0x7fffffff;

You're right, that is much simpler and more efficient. Somehow I never
caught that, thanks. :)

> 
> Of course the rules for when to convert at all are difficult to find if you 
> want consistent results for large numbers and very small numbers close to 
> zero (esp. a very small negative and a very small positive number that 
> should compare to "sufficiently equal", while eg. -200 and +200 should 
> compare to "not equal").

And -200 and +200 don't compare to equal. Try it.

Matter of fact, I attached a small source with test case to the e-mail.
Ran it with both the original code and your suggestion of using &=
0x7FFFFFFF and either way it works happily.


> > If there is no error, a-b = 0.
> > The greater the error is the larger a-b will be. You simply set MaxError
> > to what you want the greatest deviation in your code to be.
> 
> I wouldn't exactly call that "simply set MaxError", since it requires some 
> expertise to calculate a good starting point for your kind of calculation.

In the end though, you'll have to set *some* kind of boundary somewhere
what error is acceptable. This method does have the advantage, in my
opinion, that magnitude does not matter. Whether or not maxError is
defined at compile time via #define or is dynamically calculated at
runtime doesn't really matter. At one point or in time or another when
doing float compares one will have to decide how much error to accept.

Plus, QT's qFuzzyCompare requires a multiply, which aside from a
performance perspective, also introduces additional error into the
compare. I think I'll run a side by side performance test sometime today
on mine VS QT's method and see what happens. 

Stephan



-------------- next part --------------
A non-text attachment was scrubbed...
Name: test.c
Type: text/x-csrc
Size: 1051 bytes
Desc: not available
Url : http://lists.qt-project.org/pipermail/qt-interest-old/attachments/20090413/4b61afd3/attachment.bin 


More information about the Qt-interest-old mailing list