Last active
August 29, 2015 13:56
-
-
Save jeka-kiselyov/9068741 to your computer and use it in GitHub Desktop.
Math: Comparing with epsilon – relative error
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// 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