Background
Consider the validation of three doubles low, width and high such that the following three rules hold true:
low < high;width > 0; andwidthfits into(high - low)“exactly” a whole number of times.
Essentially, the three values should specify a range that is to be split up into a certain number of bins, each of “exactly” equal width, with no part of the range unnaccounted for.
For example:
(A) low = -0.5, width = 0.005 and high = 0.5
would specify a range with a valid bin width, since “exactly” 200 full bins can be created, whereas
(B) low = -0.5, width = 0.275 and high = 0.5
would specify a range with an invalid bin width, since 3 full bins could be created but part of the range is not covered by those bins.
The Problem
What is the best way approach the third validation rule, given the floating-point nature of doubles?
My first naive attempt consisted of:
fmod( high - low, width ) == 0.0
but unfortunately fmod returns 0.005 for example (A) – my debugger tells me that the double of 0.005 actually holds the value of 0.0050000000000000001.
Should I be home-brewing my own solution to include tolerances, or is there a more elegant solution to this problem?
This is what I have currently:
bool valid(double range, double width, double tolerance = 0.000000001)
{
assert(width > 0 && range > 0);
while( range > 0 && range > tolerance )
{
range -= width;
}
return abs(range) <= tolerance;
}
Note the complete and utter arbitrariness of the default value of tolerance …
Your approach using a tolerance for double comparisons is a reasonable one. The only thing you need now is to do the rest of your requirements analysis to determine how haccurate you really need to be 🙂
If you know your maximum precision, multiply up to integer values for the comparison.