std::numeric_limits<double>::epsilon() 可以用于什么?

10
  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()?


4
请注意,epsilon 是从 1 到下一个数字的距离,而不是从 0 到下一个数字的距离。在 IEEE 754 中,0 到 epsilon 之间有许多可表示的数字。 - chris
我在控制台中打印了 episilon,输出结果为 2.22045e-16。所以我关心的是它是否等于 prob_good_model < 0 - Finley
< 0 相比,它非常不同。 - M.M
@Finley,不,它不等同于< 0;在0和epsilon之间的所有数字在其结果上都有所不同。即使epsilon是从0开始的(这是mindenorm_min),对于0本身仍然会产生不同的结果。 - chris
他们只是将epsilon作为一个小数使用。虽然它与其定义无关,在某些问题中可能不够小,但有时人们将其用作足够小的度量。因此,条件prob_good_model < epsilon意味着prob_good_model足够接近于零。这里的足够是根据编写代码的人的判断而定。请注意,当概率足够接近于零时,通常情况下nusample_s公式会返回一个非常大的数字,然后他们会返回(他们认为是大数max_hypotheses_ - conditionalMethod
显示剩余6条评论
2个回答

18

epsilon的作用是让你能够相对容易地确定两个数字之间最小的差别。

但通常你不会直接使用它。你需要根据比较的数字大小进行缩放。如果你有两个约为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个数量级,但它们会显示为“true”(即相等)。反过来说,如果这些数字远大于1,则与未缩放的epsilon比较相当于说if(x != y)--它完全不留下舍入误差的余地。

至少在我的经验中,浮点类型指定的epsilon并没有太大用处。通过适当的缩放,它告诉您给定量级下两个数字之间可能存在的最小差异(对于特定的浮点实现)。

然而,在实际使用中,这在实际上意义不太大。一个更现实的数字通常将基于输入的精度,并估计由于舍入(和其他因素)可能已经丢失了多少精度。

例如,假设您从每百万份之一的精度开始,只进行了几次计算,所以您认为可能因为舍入误差而失去了2位数的精度。在这种情况下,你关心的“ epsilon ”大约是1e-4,按照你处理的数字的大小来缩放。也就是说,在这种情况下,您可以预期有大约4个数字的精度是有意义的,因此如果您看到前四个数字的差异,则可能意味着值不相等,但如果它们仅在第五个(或更后面)数字上有差异,则应该将它们视为相等。

您使用的浮点类型可以表示(例如)16位数字的精度并不意味着您使用的每个测量都希望接近精确——事实上,基于物理测量的任何东西都很少能够接近那样精确。然而,它确实给您一个计算的期望上限——即使您从一个精确到,比如说,30位数开始,您在计算之后能够期望的最多也只能由std::numeric_limits<T>::epsilon定义。


3
从信号处理工程的角度来看,epsilon看起来像一个“噪声底噪”。将你估算的精度与噪声底噪(实践中的比率对数)进行比较,可以得到一个以分贝为单位的数字,称为“噪声余量”,可以用作检查您的浮点类型是否足够精确的方法,或者相反地引发警报。如果不这样做,意味着您的计算可能会因为浮点类型过短而默默出错。 - Stéphane Gourichon
3
Epsilon是两个数字之间的最大相对误差。这意味着将其乘以数字的大小,它就是两个数字之间的最大差异。使用Epsilon的一个例子是衡量计算误差是否“可接受”。如果通过某种方法计算出一个值为 x,而另一种方法得到 y,那么如果 abs(x-y)<=epsilon*abs(x),则相对误差不会超过在 x 的规模下可以产生的最大相对误差。人们可以判断 yx 的一个可接受近似值。 - conditionalMethod
@conditionalMethod: [抱歉,我发帖时显然漏掉了这一点] 适当缩放的 epsilon 值给出了可以表示的最小差异。因此,“abs(x-y)<=epsilon*abs(x)” 是没有意义的。“<” 部分根本不可能实现,所以这等效于说 “if (x == y)”,允许两种计算方法之间完全没有差异。 - Jerry Coffin

0

它可以用于函数未定义的情况,但在那一点仍需要一个值。你失去了一些准确性,特别是在极端情况下,但有时这也无妨。

比如说,你正在使用 1/x,但 x 的范围是 [0,n[。你可以使用 1/(x + std::numeric_limits<double>::epsilon()),这样 0 就仍然被定义。话虽如此,你必须小心地使用这个值,它可能不适用于每种情况。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接