Efficient double comparison

D

Dave

Hello all,

I would like to solicit suggestions on how to most efficiently accomplish
something. I have profiled the project I'm working on and have found that
calls to fabs() are taking a very substantial amount of time. fabs() is
being used in the following manner:

double a, b;

a = get_a_value();
b = get_another_value();

if (fabs(a - b) > 1E-9)
// Do "not equal" stuff
else
// Do "equal" stuff

So, we're simply comparing two doubles for equality and making allowances
for inexact numeric representation.

Of course, we could save time by reducing the number of comparisons. But,
unfortunately, we do need all of the comparisons we're making - none are
redundant or unused. So... Can anybody out there suggest a more efficient
way of accomplishing these comparisons?

Thanks,
Dave
 
C

Claudio Puviani

Dave said:
Hello all,

I would like to solicit suggestions on how to most efficiently accomplish
something. I have profiled the project I'm working on and have found that
calls to fabs() are taking a very substantial amount of time. fabs() is
being used in the following manner:

double a, b;

a = get_a_value();
b = get_another_value();

if (fabs(a - b) > 1E-9)
// Do "not equal" stuff
else
// Do "equal" stuff

So, we're simply comparing two doubles for equality and making allowances
for inexact numeric representation.

Of course, we could save time by reducing the number of comparisons. But,
unfortunately, we do need all of the comparisons we're making - none are
redundant or unused. So... Can anybody out there suggest a more efficient
way of accomplishing these comparisons?

You can always do something like this:

inline bool simpleFuzzyEq(const double & v1, const double & v2, const double &
epsilon)
{
const double diff = v1 - v2;

return diff < epsilon && diff > -epsilon;
}

The extra comparison is far less expensive than a call to fabs() and most
compilers will inline this to something extremely tight.

As a side note, a fuzzy equality test with an absolute epsilon has an extremely
limited scope and doesn't behave intuitively if the magnitudes of a comparand is
very large.

Claudio Puviani
 
M

Marcin Kalicinski

Hi,

inline bool simpleFuzzyEq(const double & v1, const double & v2, const double
&
epsilon)
{
const double diff = v1 - v2;

The extra comparison is far less expensive than a call to fabs() and most
compilers will inline this to something extremely tight.

This is something I absolutely cannot agree about, at least for Intel 80x86
architecture. FABS operation done in 80x86 FPU takes exactly 1 cycle, and
also pairs with the next operation (if they're not dependent). Practically -
it is free. Comparison between 2 floating point numbers is a complex thing
on the other hand. It can take as much as 4 cycles, plus extra instructions
to copy the result from FPU registers to CPU registers (to actually do the
conditional jump based on comparison result). Not to say that in the code
above there is an extra unary negation op, which has usually the same
complexity as FABS alone. And an extra '&&' operation...

I don't know other CPU architectures, but I think it's the same way round.

On 80x86, if precision up to 15th digit is not very important, I'd suggest
switching to float data and using _control87() to force FPU to work in
24-bit precision mode. _control87() is non-standard, but present in most
80x86 compilers libraries:

_control87(_PC_24, MCW_PC); // reduce precision
// here put plenty of intensive floating point operations. They'll work much
faster

_control87(_PC_53, MCW_PC); // restore precision

Best regards,
Marcin

U¿ytkownik "Claudio Puviani" <[email protected]> napisa³ w wiadomoœci
Dave said:
Hello all,

I would like to solicit suggestions on how to most efficiently accomplish
something. I have profiled the project I'm working on and have found that
calls to fabs() are taking a very substantial amount of time. fabs() is
being used in the following manner:

double a, b;

a = get_a_value();
b = get_another_value();

if (fabs(a - b) > 1E-9)
// Do "not equal" stuff
else
// Do "equal" stuff

So, we're simply comparing two doubles for equality and making allowances
for inexact numeric representation.

Of course, we could save time by reducing the number of comparisons. But,
unfortunately, we do need all of the comparisons we're making - none are
redundant or unused. So... Can anybody out there suggest a more efficient
way of accomplishing these comparisons?

You can always do something like this:

inline bool simpleFuzzyEq(const double & v1, const double & v2, const double
&
epsilon)
{
const double diff = v1 - v2;

return diff < epsilon && diff > -epsilon;
}

The extra comparison is far less expensive than a call to fabs() and most
compilers will inline this to something extremely tight.

As a side note, a fuzzy equality test with an absolute epsilon has an
extremely
limited scope and doesn't behave intuitively if the magnitudes of a
comparand is
very large.

Claudio Puviani
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,577
Members
45,054
Latest member
LucyCarper

Latest Threads

Top