FP_Compare

int FP_Compare (double numberA, double numberB);

Purpose

Compares two floating point numbers for equality using a small tolerance factor to compensate for the inability to precisely represent some numbers and the error inherent in successive floating point operations.

Comparing floating point numbers for equality can be tricky because results can differ infinitesimally depending on how the calculation is performed.

For example, consider the results given by the following code when run under the listed compilers.

#include <stdio.h>
#include <math.h>

/* from toolbox.h (more precision than can be represented) */
#define PI 3.1415926535897932384626433832795028841971

main()
{

/* Test 1 */

if (acos(–1) == PI)

printf("acos(–1) == PI Succeeded\n");

else

printf("Huh? acos(–1) and PI should be equal!!\n");

/* Test 2 */

if (1/acos(–1) == 1/PI)

printf("1/acos(–1) == 1/PI Succeeded\n");

else

printf("Huh? 1/acos(–1) == 1/PI should be equal!!\n");

}

Here are the results for a few compilers:

Compiler Test 1 Test 2
CVI for Windows 3.1 Passed Failed
CVI for Windows 95 Passed Failed
Visual C++ 1.5 Passed Failed
Visual C++ 2.0 Failed Passed
Think C 6.0 on Quadra (Macintosh) Failed Failed
CVI for Sparc Passed Passed
ACC for Sparc Passed Passed
CC for Sparc Failed Failed

The reasons for the differing results on the previous tests can depend on subtle issues such as when the compiler chooses to remove values from the co–processor, whether an alternate math library is being used, or even if a Pentium division bug patch is installed.

Failing a test is NOT a sign the compiler is doing something wrong. For example, keeping the operands of an operation in the co–processor can increase accuracy of a result. If this more accurate result is compared with a result that required intermediate values to be stored outside of the co–processor, then an equality test on the resulting values may fail. This is not the compiler's fault, since it was performing the arithmetic as precisely as was possible.

In addition, different tests and different ways of writing the above tests will give a different set of results.

The bottom line is that using "==" to compare floating point numbers may yield surprising results.

For instances where you want to test if two numbers are 'virtually equal', you can use this function to make the comparison.

FP_Compare works by comparing the ratio of the two numbers and comparing how close this ratio is to 1. This method is better than simply comparing the difference of the two numbers because it compensates for the magnitude of the numbers.

If the difference between A and B is less than FP_CompareEpsilon, then the comparison between A and B is made using the following formula (with appropriate handling of zero and negative values):

1 – A/B > FP_CompareEpsilon

(The value of FP_CompareEpsilon is #defined in toolbox.h)

Parameters

Input
Name Type Description
numberA double Pass the value to compare to number B.
numberB double Pass the value to compare to number A.

Return Value

Name Type Description
result integer Returns 0 if number A is equal to number B (within a small tolerance).

Returns 1 if number A is greater than number B.

Returns –1 if number A is less than number B.