What is the correct use of approxEqual ()?

At first I thought I could only rely on the maximum relative difference, but I was wrong. For example, if a = 0.0 and b = 0.5 , their relative difference is 1.0 . In this case, approxEquals(lhs, rhs, maxRelDiff, maxAbsDiff) relies on the maximum absolute difference to determine if two floating-point numbers are equal.

Two questions:

  • How can I get a new maximum relative and absolute difference pair if the default value (1e-2, 1e-5) is not accurate enough? How were 1e-2 and 1e-5 selected as default values? For example, if I choose 1e-4 as the maximum relative difference, what is the maximum absolute difference?

  • How to configure the maximum relative and absolute values โ€‹โ€‹of the difference to work correctly with floats and doubles ?

+4
source share
2 answers

checking the source code gives me this (I cut out implementations for ranges)

 bool approxEqual(T, U, V)(T lhs, U rhs, V maxRelDiff, V maxAbsDiff = 1e-5) { if (rhs == 0) { return fabs(lhs) <= maxAbsDiff; } static if (is(typeof(lhs.infinity)) && is(typeof(rhs.infinity))) { if (lhs == lhs.infinity && rhs == rhs.infinity || lhs == -lhs.infinity && rhs == -rhs.infinity) return true; } return fabs((lhs - rhs) / rhs) <= maxRelDiff || maxAbsDiff != 0 && fabs(lhs - rhs) <= maxAbsDiff; } 

The last line is what we need to learn:

 return fabs((lhs - rhs) / rhs) <= maxRelDiff || maxAbsDiff != 0 && fabs(lhs - rhs) <= maxAbsDiff; 

In other words, the function returns true if the numbers either differ from each other by no more than a factor maxRelDiff OR are completely different no more than by maxAbsDiff

therefore, using maxRelDiff of 0.01 (or 1E-2 ) is compared to within 2 (decimal) digits

and using maxAbsDiff other than 0 allows us to consider numbers close to 0 equal, although the relative difference is greater than maxRelDiff

edit : first, first determine how accurate the comparison should be, and select your maxRelDiff based on this, then determine at what point the number 0 should be

with examples in the comments:

 approxEqual(1+1e-10, 1.0, 1e-10, 1e-30) approxEqual(1+1e-10, 1.0, 1e-9, 1e-30) 

this compares values โ€‹โ€‹close to 1, so maxRelDiff trumps here and choosing any maxAbsDiff (below maxRelDiff ) will not change anything

 approxEqual(0, 1e-10, 1e-10, 1e-30) approxEqual(0, 1e-9, 1e-9, 1e-30) 

it compares the value close to 0 to 0, so RelDiff ( fabs((lhs - rhs) / rhs) ) is 1 and maxAbsDiff trumps

+1
source

Although I cannot answer your original question, I personally just use fabs to compare with a floating point:

 return fabs(f1 - f2) < 0.10; 
0
source

Source: https://habr.com/ru/post/1388868/


All Articles