[Qt-interest] strange qFuzzyCompare implementation
Reinhardt Behm
reinhardt.behm at t-online.de
Mon Apr 13 17:13:09 CEST 2009
On Monday 13 April 2009 14:13, Stephan Rose wrote:
> 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
Your "solution" is totally unportable because your assumptions about the
representation of float numbers will only be correct on a x86 evironment. And
even there some compiler implementation might store floats differently.
Try running it on e.g. an ARM platform and it will not word at all. This is no
solution for a multiplatform toolkit like Qt.
Besides it is bad programming style to rely on such undocumented behaviour.
--
Reinhardt Behm
reinhardt.behm at t-online.de
More information about the Qt-interest-old
mailing list