为什么 numeric_limits Machine Epsilon 不满足 1+e>1 条件?

时间:2020-12-24 02:36:39

标签: c++ floating-point precision floating-accuracy epsilon

如果我没记错的话,Machine Epsilon 的定义是满足条件的最低数字:

1+e>1

我试图使用 std::numeric_limits<float>::epsilon() 来测试这个,但如果您尝试使用 std::nextafter 获取先前的浮点数,则该值不满足这一点:

#include <cmath>
#include <iostream>
#include <limits>

int main() {
    float e = std::numeric_limits<float>::epsilon();
    float previous = std::nextafter(e, -std::numeric_limits<float>::infinity());

    std::cout << std::boolalpha << ((1.0f + previous) > 1.0f) << std::endl;

    return 0;
}

这仍然输出 true https://coliru.stacked-crooked.com/a/841e19dafcf0bf6f

在尝试使用 std::nextafter 获取数字后,我注意到正确的 Machine Epsilon 应该是:

std::nextafter(std::numeric_limits<float>::epsilon() / 2.0f, std::numeric_limits<float>::infinity())

我使用此代码对其进行了测试:

#include <cmath>
#include <iostream>
#include <limits>

bool verify(float e) {
    return ((1.0f + e) > 1.0f);
}

int main() {
    std::cout.precision(std::numeric_limits<float>::digits);
    std::cout << std::boolalpha << std::fixed;

    float epsilon = std::numeric_limits<float>::epsilon();

    float last = epsilon;
    while (true) {
        last = std::nextafter(last, -std::numeric_limits<float>::infinity());
        if ((1.0f + last) > 1.0f) {
            epsilon = last;
        } else {
            break;
        }
    }

    // Does not satisfy condition
    std::cout << "last: " << verify(last) << " " << last << std::endl;
    // Satisfy condition
    std::cout << "epsilon: " << verify(epsilon) << " " << epsilon << std::endl;

    float half_epsilon = std::numeric_limits<float>::epsilon() / 2.0f;
    float actual_epsilon = std::nextafter(half_epsilon, std::numeric_limits<float>::infinity());
    // Same as 'last' at this point
    std::cout << "half_epsilon: " << verify(half_epsilon) << " " << half_epsilon << std::endl;
    // Same as 'epsilon' at this point
    std::cout << "actual_epsilon: " << verify(actual_epsilon) << " " << actual_epsilon << std::endl;

    return 0;
}

这个输出

last: false 0.000000059604644775390625
epsilon: true 0.000000059604651880817983
half_epsilon: false 0.000000059604644775390625
actual_epsilon: true 0.000000059604651880817983

https://coliru.stacked-crooked.com/a/3c66a2144e80a91b

我在这里遗漏了什么吗?

0 个答案:

没有答案
相关问题