Skip to content

Instantly share code, notes, and snippets.

@jeka-kiselyov
Last active August 29, 2015 13:56
Show Gist options
  • Save jeka-kiselyov/9068741 to your computer and use it in GitHub Desktop.
Save jeka-kiselyov/9068741 to your computer and use it in GitHub Desktop.
Math: Comparing with epsilon – relative error
/// Always forget it
/// Source: http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm
relativeError = fabs((result - expectedResult) / expectedResult);
// If result is 99.5, and expectedResult is 100, then the relative error is 0.005.
// Sometimes we don’t have an ‘expected’ result, we just have two numbers that we want to compare to see if they are almost equal. // We might write a function like this:
// Non-optimal AlmostEqual function - not recommended.
bool AlmostEqualRelative(float A, float B, float maxRelativeError)
{
if (A == B)
return true;
float relativeError = fabs((A - B) / B);
if (relativeError <= maxRelativeError)
return true;
return false;
}
// Slightly better AlmostEqual function – still not recommended
bool AlmostEqualRelative2(float A, float B, float maxRelativeError)
{
if (A == B)
return true;
float relativeError;
if (fabs(B) > fabs(A))
relativeError = fabs((A - B) / B);
else
relativeError = fabs((A - B) / A);
if (relativeError <= maxRelativeError)
return true;
return false;
}
// Slightly better AlmostEqual function – still not recommended
bool AlmostEqualRelativeOrAbsolute(float A, float B,
float maxRelativeError, float maxAbsoluteError)
{
if (fabs(A - B) < maxAbsoluteError)
return true;
float relativeError;
if (fabs(B) > fabs(A))
relativeError = fabs((A - B) / B);
else
relativeError = fabs((A - B) / A);
if (relativeError <= maxRelativeError)
return true;
return false;
}
// Usable AlmostEqual function
bool AlmostEqual2sComplement(float A, float B, int maxUlps)
{
// Make sure maxUlps is non-negative and small enough that the
// default NAN won't compare as equal to anything.
assert(maxUlps > 0 && maxUlps < 4 * 1024 * 1024);
int aInt = *(int*)&A;
// Make aInt lexicographically ordered as a twos-complement int
if (aInt < 0)
aInt = 0x80000000 - aInt;
// Make bInt lexicographically ordered as a twos-complement int
int bInt = *(int*)&B;
if (bInt < 0)
bInt = 0x80000000 - bInt;
int intDiff = abs(aInt - bInt);
if (intDiff <= maxUlps)
return true;
return false;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment