Для чего можно использовать std::numeric_limits‹double›::epsilon()?

  unsigned int updateStandardStopping(unsigned int numInliers, unsigned int totPoints, unsigned int sampleSize)
    {
        double max_hypotheses_=85000;
        double n_inliers = 1.0;
        double n_pts = 1.0;
        double conf_threshold_=0.95

        for (unsigned int i = 0; i < sampleSize; ++i)
        {
            n_inliers *= numInliers - i;//n_linliers=I(I-1)...(I-m+1)
            n_pts *= totPoints - i;//totPoints=N(N-1)(N-2)...(N-m+1)
        }
        double prob_good_model = n_inliers/n_pts;

        if ( prob_good_model < std::numeric_limits<double>::epsilon() )
        {
            return max_hypotheses_;
        }
        else if ( 1 - prob_good_model < std::numeric_limits<double>::epsilon() )
        {
            return 1; 
        }
        else 
        {
            double nusample_s = log(1-conf_threshold_)/log(1-prob_good_model);
            return (unsigned int) ceil(nusample_s); 
        }
    }

Вот заявление о выборе:

if ( prob_good_model < std::numeric_limits<double>::epsilon() )
{...}

Насколько я понимаю, суждение такое же, как (или приближение к)

prob_good_model < 0

Так прав ли я или нет, и где еще можно использовать std::numeric_limits<double>::epsilon()?


person Finley    schedule 07.01.2018    source источник
comment
Обратите внимание, что эписилон — это расстояние от 1 до следующего числа, а не от 0 до следующего числа. В IEEE 754 существует много представляемых чисел между 0 и эпсилон.   -  person chris    schedule 07.01.2018
comment
Я напечатал эписилон в консоли, и на выходе 2.22045e-16. Так что меня здесь волнует, равно ли оно prob_good_model < 0   -  person Finley    schedule 07.01.2018
comment
Это сильно отличается от < 0   -  person M.M    schedule 07.01.2018
comment
@Finley, нет, это не эквивалентно < 0; все числа между 0 и эпсилон отличаются по своему результату. Даже если бы эпсилон был от 0 (это min или denorm_min), это все равно был бы другой результат для самого 0.   -  person chris    schedule 07.01.2018
comment
@chris Итак, каково истинное значение prob_good_model < std::numeric_limits<double>::epsilon()? Можете ли вы дать мне разумное предположение?   -  person Finley    schedule 07.01.2018
comment
@chris или он просто представляет, что переменная prob_good_model меньше очень маленького числа, но не 0.   -  person Finley    schedule 07.01.2018
comment
Если вы нашли это, скорее всего, это попытка увидеть, равно ли prob_good_model 0 с некоторым допуском для ошибки округления. Тем не менее, он рассматривает что-то вроде prob_good_model = 1e-20 как равное 0, несмотря на то, что эти два значения довольно далеки для арифметических операций, выполняемых с очень маленькими значениями. Важно ли это различие, зависит от кода вокруг этого. Возможно, нет никаких шансов, что он когда-либо создаст значение ниже 10 ^ -16, которое он не хочет рассматривать как 0.   -  person chris    schedule 07.01.2018
comment
@chris Я разместил вокруг него коды, можешь проверить еще раз? благодарю вас:)   -  person Finley    schedule 07.01.2018
comment
Лично я думаю, что этот конкретный случай делает, и дополнительный код, необходимый для его демонстрации, отвлекает от вопроса о том, для чего используется эпсилон. В любом случае, у меня нет большой интуиции для статистики (и для плавающей запятой, пока я этим занимаюсь), но я бы сказал, что для этого варианта использования, вероятно, приемлемо использование эпсилон. Я бы также сказал, что вероятность возникновения ошибки из-за нее увеличивается при значительном размере выборки.   -  person chris    schedule 07.01.2018
comment
Они используют epsilon просто как небольшое число. Хотя это не связано с его определением, и в некоторых задачах оно может быть недостаточно маленьким, иногда люди используют его как меру достаточно малого. Итак, условие prob_good_model < epsilon означает, что prob_good_model достаточно близко к нулю. Здесь достаточно по мнению того, кто написал код. Обратите внимание, что когда вероятность достаточно близка к нулю, то формула для nusample_s в общем случае вернет очень большое число, тогда они возвращают (то, что они считают большим числом) max_hypotheses_.   -  person conditionalMethod    schedule 27.09.2019
comment
Точно так же 1 - prob_good_model < epsilon используется здесь для обозначения того, что prob_good_model достаточно близко (для них) к 1.   -  person conditionalMethod    schedule 27.09.2019


Ответы (1)


Смысл эпсилона в том, чтобы вам (довольно) было легко вычислить наименьшую разницу, которую вы могли бы увидеть между двумя числами.

Однако обычно вы не используете его точно так, как есть. Вам нужно масштабировать его на основе величин чисел, которые вы сравниваете. Если у вас есть два числа в диапазоне от 1e до 100, вы должны использовать что-то порядка: std::numeric_limits<double>::epsilon() * 1.0e-100 в качестве стандарта сравнения. Точно так же, если ваши числа составляют около 1e+100, ваш стандарт будет std::numeric_limits<double>::epsilon() * 1e+100.

Если вы попытаетесь использовать его без масштабирования, вы можете получить совершенно неправильные (совершенно бессмысленные) результаты. Например:

if (std::abs(1e-100 - 1e-200) < std::numeric_limits<double>::epsilon())

Да, это будет отображаться как «истина» (т.е. сказать, что они равны), даже если они отличаются на 100 порядков. С другой стороны, если числа намного больше 1, сравнение с (немасштабированным) эпсилоном эквивалентно выражению if (x != y) - оно вообще не оставляет места для ошибок округления.

По крайней мере, по моему опыту, epsilon, указанный для типа с плавающей запятой, не часто используется. При правильном масштабировании он сообщает вам наименьшую разницу, которая может быть между двумя числами заданной величины (для конкретной реализации с плавающей запятой).

Однако в реальном использовании это имеет относительно мало реального применения. Более реалистичное число обычно будет основано на точности входных данных и оценке степени точности, которую вы, вероятно, потеряли из-за округления (и тому подобного).

Например, давайте предположим, что вы начали со значений, измеренных с точностью до 1 части на миллион, и сделали лишь несколько вычислений, поэтому вы считаете, что могли потерять целых 2 цифры точности из-за ошибок округления. В этом случае «эпсилон», о котором вы заботитесь, составляет примерно 1e-4, масштабированный до величины чисел, с которыми вы имеете дело. Другими словами, при таких обстоятельствах вы можете ожидать, что точность порядка 4 цифр будет иметь смысл, поэтому, если вы видите разницу в первых четырех цифрах, это, вероятно, означает, что значения не равны, но если они различаются только в пятой (или более поздней) цифре, вы, вероятно, должны относиться к ним как к равным.

Тот факт, что тип с плавающей запятой, который вы используете, может представлять (например) 16 цифр точности, не означает, что каждое используемое вами измерение будет почти точным — на самом деле, относительно редко что-либо основанное на физических данных. измерения имеют любую надежду быть хотя бы близкими к этой точности. Однако это дает вам ограничение на то, на что вы можете надеяться при расчете — даже если вы начинаете со значения, которое точно соответствует, скажем, 30 цифрам, самое большее, на что вы можете надеяться после расчета, будет определяться std::numeric_limits<T>::epsilon.

person Jerry Coffin    schedule 07.01.2018
comment
С точки зрения техники обработки сигналов эпсилон выглядит как минимальный уровень шума. Сравнение вашей предполагаемой точности с минимальным уровнем шума (на практике логарифм отношения) дает вам число в децибелах, которое вы можете назвать запасом по шуму и использовать как способ проверить, достаточно ли точен ваш тип поплавка, или, наоборот, увеличить тревога. Невыполнение этого означает, что ваши вычисления могут быть ошибочными из-за слишком короткого типа с плавающей запятой. - person Stéphane Gourichon; 25.09.2019
comment
Эпсилон — это максимальная относительная ошибка между двумя числами. Это означает, что, умноженное на величину чисел, получается максимальная разница между двумя числами. Одним из примеров использования является измерение того, является ли ошибка вычислений приемлемой. Если вычислить значение каким-либо методом и получить x, а другим — y, то если abs(x-y)<=epsilon*abs(x), относительная ошибка не больше, чем максимальная относительная ошибка, которую можно сделать в масштабе x. Можно судить, что y является приемлемым приближением к y. - person conditionalMethod; 27.09.2019