4

The DBL_EPSILON/std::numeric_limits::epsilon will give me the smallest value that will make a difference when adding with one.

I'm having trouble understanding how to apply this knowledge into something useful.

The epsilon is much larger than the smallest value the computer can handle, so It would seem like a correct assumption that its safe to use smaller values than epsilon?

Should the ratio between the values I'm working with be smaller than 1/epsilon ?

monkeyking
  • 6,670
  • 24
  • 61
  • 81

2 Answers2

4

The definition of DBL_EPSILON isn't that. It is the difference between the next representable number after 1 and 1 (your definition assumes that the rounding mode is set to "toward 0" or "toward minus infinity", that's not always true).

It's something useful if you know enough about numerical analysis. But I fear this place is not the best one to learn about that. As an example, you could use it in building a comparison function which would tell if two floating point numbers are approximatively equal like this

bool approximatively_equal(double x, double y, int ulp)
{
   return fabs(x-y) <= ulp*DBL_EPSILON*max(fabs(x), fabs(y));
}

(but without knowing how to determine ulp, you'll be lost; and this function has probably problems if intermediate results are denormals; fp computation is complicated to make robust)

Stefan
  • 1,131
  • 2
  • 12
  • 30
AProgrammer
  • 51,233
  • 8
  • 91
  • 143
  • 1
    `approximately_equal` isn't going to work correctly for very large values, since the size of the interval between the current and next nearest representable value in a double changes with magnitude (because the exponent changes). Doing this appropriately would require recalculating a contextually-accurate epsilon based on the value being compared. – numist Sep 17 '13 at 21:00
  • 1
    @numist, multiplying epsilon by `max(fabs)` should give the correct magnitude, and the ulp argument allow to give context information about the relative error already accumulated. If you still think there is a problem, could you be more clear its the source? – AProgrammer Sep 18 '13 at 04:54
  • 2
    Epsilon is not proportional in continuous manner. With IEEE encoding, epsilon is proportional to a value in discrete manner on base 2. http://stackoverflow.com/questions/5064377/c-comparing-two-floating-point-values/35536839#35536839 – Daniel Laügt Feb 21 '16 at 14:34
2

The difference between X and the next value of X varies according to X.
DBL_EPSILON is only the difference between 1 and the next value of 1.

You can use std::nextafter for testing two double with epsilon difference:

bool nearly_equal(double a, double b)
{
  return std::nextafter(a, std::numeric_limits<double>::lowest()) <= b
&& std::nextafter(a, std::numeric_limits<double>::max()) >= b;
}

If you would like to test two double with factor * epsilon difference, you can use:

bool nearly_equal(double a, double b, int factor /* a factor of epsilon */)
{
  double min_a = a - (a - std::nextafter(a, std::numeric_limits<double>::lowest())) * factor;
  double max_a = a + (std::nextafter(a, std::numeric_limits<double>::max()) - a) * factor;

  return min_a <= b && max_a >= b;
}
Daniel Laügt
  • 1,097
  • 1
  • 12
  • 17