int FP_Compare (double numberA, double numberB);
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(
printf("acos(
else
printf("Huh? acos(
/* Test 2 */
if (1/acos(
printf("1/acos(
else
printf("Huh? 1/acos(
}
Here are the results for a few compilers:
Compiler | Test 1 | Test 2 |
---|---|---|
Passed | Failed | |
Passed | Failed | |
Passed | Failed | |
Failed | Passed | |
Failed | Failed | |
Passed | Passed | |
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)
Input | ||
Name | Type | Description |
numberA | double | Pass the value to compare to number B. |
numberB | double | Pass the value to compare to number A. |
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 |