【问题标题】:What can std::numeric_limits<double>::epsilon() be used for?std::numeric_limits<double>::epsilon() 可以用来做什么?
【发布时间】:2018-06-16 10:40:25
【问题描述】:
  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&lt;double&gt;::epsilon()还能用在哪里?

【问题讨论】:

  • 请注意,epsilon 是从 1 到下一个数字的距离,而不是从 0 到下一个数字的距离。在 IEEE 754 中,0 到 epsilon 之间有许多可表示的数字。
  • 我在控制台打印了epsilon,输出为2.22045e-16。所以我这里关心的是它是否等于prob_good_model &lt; 0
  • &lt; 0很不一样
  • @Finley,不,它不等同于&lt; 0; 0 和 epsilon 之间的所有数字的结果都不同。即使 epsilon 来自 0(这是 mindenorm_min),对于 0 本身来说仍然是不同的结果。
  • @chris 那么prob_good_model &lt; std::numeric_limits&lt;double&gt;::epsilon()的真正含义是什么?你能给我一个合理的推测吗?

标签: c++ std numeric-limits


【解决方案1】:

epsilon 的目的是让您(相当)容易地计算出两个数字之间可以看到的最小差异。

不过,您通常不会完全按原样使用它。您需要根据要比较的数字的大小对其进行缩放。如果您有两个 1e-100 左右的数字,那么您将使用以下顺序:std::numeric_limits&lt;double&gt;::epsilon() * 1.0e-100 作为比较标准。同样,如果您的数字在 1e+100 左右,您的标准将是std::numeric_limits&lt;double&gt;::epsilon() * 1e+100

如果您尝试在不缩放的情况下使用它,您可能会得到非常不正确(完全没有意义)的结果。例如:

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

是的,即使它们相差 100 个数量级,这也会显示为“真实”(即说两者相等)。在另一个方向上,如果数字远大于 1,则与(未缩放的)epsilon 相比就相当于说if (x != y)——它根本没有舍入误差的余地。

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

然而,在实际使用中,它的实际用途相对较小。更现实的数字通常基于输入的精度,以及您可能因四舍五入(等等)而损失的精度的估计值。

例如,假设您从测量精度为百万分之 1 的值开始,并且只进行了几次计算,因此您认为由于舍入误差,您可能损失了多达 2 位数的精度。在这种情况下,您关心的“epsilon”大约是 1e-4,按比例缩放到您正在处理的数字的大小。也就是说,在这种情况下,您可以期望 4 位数的精度是有意义的,所以如果您看到前四位数有差异,这可能意味着值不相等,但如果它们不同仅在第五个(或更高)数字中,您应该将它们视为平等。

您使用的浮点类型可以表示(例如)16 位精度,但这并不意味着您使用的每次测量都几乎是精确的——事实上,任何东西都比较少见基于物理测量的任何希望甚至接近那个精确度。但是,它确实限制了您对计算的期望——即使您从一个精确到 30 位的值开始,计算后您可以期望的最大值将由下式定义std::numeric_limits&lt;T&gt;::epsilon.

【讨论】:

  • 从信号处理工程的角度来看,epsilon 看起来像一个“本底噪声”。将您的估计精度与本底噪声(实际上是比率的对数)进行比较,您可以得到一个以分贝为单位的数字,您可以将其称为“噪声容限”,并且可以用作检查您的浮点类型是否足够精确的一种方法,或者相反发出警报。不这样做意味着你的计算可能会因为浮点类型太短而默默地出错。
  • epsilon 是两个数字之间的最大相对误差。这意味着乘以数字的大小,它是两个数字之间的最大差。使用的一个例子是测量计算的误差是否可接受。如果一个人通过某种方法计算一个值并得到x,而另一个得到y,那么如果abs(x-y)&lt;=epsilon*abs(x) 相对误差不大于在x 的范围内可以产生的最大相对误差。可以判断yy 的可接受近似值。
  • @conditionalMethod: [对不起,我在发布时显然错过了这个] 不。适当缩放的 epsilon 值给出了可以表示的 最小 差异。所以abs(x-y)&lt;=epsilon*abs(x) 没有意义。 &lt; 部分根本不可能,所以这相当于说if (x == y),这两种计算方法之间根本没有区别。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-12-21
  • 1970-01-01
  • 1970-01-01
  • 2019-05-06
  • 2018-07-20
  • 2021-04-02
  • 1970-01-01
相关资源
最近更新 更多