Когда использовать DBL_EPSILON / epsilon - PullRequest
4 голосов
/ 24 июня 2010

DBL_EPSILON / std :: numeric_limits :: epsilon даст мне наименьшее значение, которое будет иметь значение при добавлении с одним.

У меня проблемы с пониманием, как применить эти знания во что-то полезное.

Эпсилон намного больше, чем наименьшее значение, которое может обработать компьютер, поэтому кажется правильным предположить, что безопаснее использовать меньшие значения, чем эпсилон?

Должно ли соотношение между значениямиЯ работаю с быть меньше, чем 1 / эпсилон?

Ответы [ 2 ]

4 голосов
/ 24 июня 2010

Определение DBL_EPSILON не так.Это разница между следующим представимым числом после 1 и 1 (ваше определение предполагает, что режим округления установлен на «к 0» или «к минус бесконечности», это не всегда так).

Это что-то полезноеесли вы знаете достаточно о численном анализе.Но я боюсь, что это место не лучшее, чтобы узнать об этом.В качестве примера, вы можете использовать ее при построении функции сравнения, которая скажет, равны ли приблизительно два числа с плавающей запятой примерно так:

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

(но не зная, как определить ulp, вы потеряетесь;и эта функция, вероятно, имеет проблемы, если промежуточные результаты являются ненормированными; вычисление fp сложно сделать надежным)

1 голос
/ 07 февраля 2016

Разница между X и следующим значением X варьируется в зависимости от X.
DBL_EPSILON - это только разница между 1 и следующим значением 1.

Вы можете использовать std::nextafter для тестирования двух double с разницей эпсилон:

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

Если вы хотите протестировать два double с разностью коэффициента * эпсилон, вы можете использовать:

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