0

Background

Consider the validation of three doubles low, width and high such that the following three rules hold true:

  1. low < high;
  2. width > 0; and
  3. width fits 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 ...

JimmidyJoo
  • 10,503
  • 7
  • 27
  • 30
  • Why are you using doubles? This is an application they're not particularly well suited for. Why not use rationals or fixed point? – David Schwartz Jun 19 '12 at 10:42
  • 3
    Is it necessarily a failure for the width ofthe final histogram bin to be narrower than the other bins to the order of 10^-10? It is in the nature of floating point systems that you're going to have little fuzzy bits at the end, after all. – Rook Jun 19 '12 at 10:44
  • @DavidSchwartz - The values are actually typed in by users in a GUI, and so arrive to me as strings I could easily cast to whatever I choose. Perhaps the answer does lie in simply not using doubles. – JimmidyJoo Jun 19 '12 at 11:14
  • @Rook - We are using FFT's further down the line that require things to be pretty exact, but this code does not belong to me so I'm not sure *how* exact. To further complicate matters, the code is Fortran compiled using F2Py, so the doubles are going from C++ to Python to Fortran... – JimmidyJoo Jun 19 '12 at 11:14
  • I probably need to get a clearer handle on my requirements / the problem space. I had hoped for a simple "duh, just use the uber-simple, in-built library function [____]" but that was just folly. – JimmidyJoo Jun 19 '12 at 11:14

1 Answers1

1

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.

Jon Cage
  • 36,366
  • 38
  • 137
  • 215