Machine-Epsilon 似乎有两个定义:

  • 将实数四舍五入为下一个浮点数时的最大相对误差。
  • 最小正数,使得 1.0 + machine_eps != 1.0

  • 首先,我看不出这两者是如何关联的。
    第二个 DBL_EPSILON 在我的理解中不符合定义 2:

    以下程序打印:
    DBL_EPSILON:            2.220446049250313080847e-16
    DBL_EPSILON / 2:        1.110223024625156540424e-16
    1.0 + DBL_EPSILON:      1.000000000000000222045e+00
    1.0 + DBL_EPSILON / 2:  1.000000000000000000000e+00
    
    m_eps                   2.220446049250313080847e-16
    m_eps -1u               2.220446049250312834328e-16
    
    1.0 + m_eps -1u         1.000000000000000222045e+00
    
    (m_eps -1u < DBL_EPSILON):     True
    (m_eps -1u == DBL_EPSILON/2):  False
    
    m_eps -1u 应该是一个更小但非常接近 DBL_EPSILON 的数字。和
    定义 2) 1.0 + m_eps -1u 不应该评估为 1.0 吗?为什么有必要
    为此将 DBL_EPSILON 划分为 2?
    #include <stdout.h>
    #include <stdint.h>
    #inlcude <float.h>
    
    union Double_t {
        double f;
        int64_t i;
    };
    
    int main(int argc, char *argv[])
    {
        union Double_t m_eps;
    
        printf("DBL_EPSILON: \t\t%.*e\n", DECIMAL_DIG, DBL_EPSILON);
        printf("DBL_EPSILON / 2: \t%.*e\n", DECIMAL_DIG, DBL_EPSILON / 2);
    
        printf("1.0 + DBL_EPSILON: \t%.*e\n", DECIMAL_DIG, 1.0 + DBL_EPSILON);
        printf("1.0 + DBL_EPSILON / 2: \t%.*e\n", DECIMAL_DIG, 1.0 + DBL_EPSILON / 2);
    
        m_eps.f = DBL_EPSILON;
        printf("\nm_eps \t\t\t%.*e\n", DECIMAL_DIG, m_eps.f);
    
        m_eps.i -= 1;
        printf("m_eps -1u\t\t%.*e\n", DECIMAL_DIG, m_eps.f);
        printf("\n1.0 + (m_eps -1u)\t\t%.*e\n", DECIMAL_DIG, 1.0 + m_eps.f);
    
        printf("\n(m_eps -1u < DBL_EPSILON): %s\n",
                (m_eps.f < DBL_EPSILON) ? "True": "False"
                );
    
        printf("(m_eps -1u == DBL_EPSILON/2): %s\n",
                (DBL_EPSILON/2 == m_eps.f) ? "True": "False"
                );
        return 0;
    }
    

    最佳答案

    DBL_EPSILON 的错误定义,即您引用的“最小正数,使得 1.0 + machine_eps != 1”,到处都是。你甚至可以在标准库和 StackOverflow 上的其他很好的答案中找到它。当在标准库中找到时,它位于一个值附近的注释中,该值显然不对应于注释,但对应于正确的定义:



    C99 标准是这样表述的:



    这可能是造成您困惑的原因。忘记错误的定义。我写了一篇关于这个 here 的咆哮(这很像你的问题)。

    您问题中的另一个定义,“将实数四舍五入到下一个浮点数时的最大相对误差”,当四舍五入的结果是正常的浮点数时是正确的。将实数四舍五入到有限浮点数会产生一个实数的 1/2 ULP 以内的浮点数。对于普通的浮点数,这个 1/2 ULP 绝对误差会转化为一个相对误差,该误差可以在 DBL_EPSILON/2 和 DBL_EPSILON/4 之间,具体取决于浮点数在其 binade 中的位置。

    10-08 06:53