Floating Point Comparison with Epsilon

Greek EpsilonWith my recent update of Athena’s math library to use vDSP_* functions for faster math, I decided to add a unit test to all my math functions since I have had occasions where I change it and then it breaks some code elsewhere that I do not notice.

I got to writing the unit test for my vector divided by a scalar function when it started to assert. On initial look at the values printed out into the TTY they were both correct, so I extended the precision to 9 and two slightly different values.

TTY   
Calculated: 4.059524059
 
Precomputed:  4.059523582
 
Difference: 0.000000477

The values were not that far apart, and I know floating point math can differ for the same value so when comparing usually epsilon gets involved since it is the maximum error. Printing out epsilon, I discovered that the value was just slightly bigger than it making the two numbers different enough.

TTY   
Difference: 0.000000477
 
Epsilon: 0.000000119

I could just have my own custom version of epsilon but it would become incorrect for use with smaller and larger number. Or for this case in the unit test I could just use a custom compare, but I wanted something more reusable, and the first google result found me a function.

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;
}

It is a fairly simple one, rather than just comparing the difference to a larger, it determines the relative error and the user passes in a percentage of how large an error it can be.

Although they recommend on the site that you still do not use it, or now it keeps my unit test working allowing me to continue until I have read the rest of the website.