Smallest floating point positive values in C++

2019-07-21 11:04发布

What are the smallest positive values in C++ for which their multiplicative inverse will still be finite? Have tried numeric_limits<double>::epsilon() but it isn't it - am getting positive values for much smaller values than that.

#include <limits>//is it here?
void tfuuuuu()
{

   double d_eps,invd_eps;
   float f_eps,invf_eps;
   invd_eps = 1.0/d_eps;//invd_eps should be finite
   invf_eps = 1.f/f_eps;//invf_eps should be finite

}

标签: c++ precision
2条回答
ら.Afraid
2楼-- · 2019-07-21 11:49

I doubt there is a standard library function for finding the number you need, however, it is not too hard to find the needed value using a simple binary search:

#include <iostream>
#include <cmath>
#include <typeinfo>

template<typename T> T find_magic_epsilon(T from, T to) {
    if (to == std::nextafter(from, to)) return to;
    T mid = (from + to)/2;
    if (std::isinf((T)1.0/mid)) return find_magic_epsilon<T>(mid, to);
    else return find_magic_epsilon<T>(from, mid);
}

template<typename T> T meps() {
    return find_magic_epsilon<T>(0.0, 0.1);
}

template<typename T> T test_meps() {
    T value = meps<T>();
    std::cout << typeid(T).name() << ": MEPS=" << value
              << " 1/MEPS=" << (T)1.0/value << " 1/(MEPS--)="
              << (T)1.0/std::nextafter(value,(T)0.0) << std::endl;
}

int main() {
    test_meps<float>();
    test_meps<double>();
    test_meps<long double>();
    return 0;
}

The output of the script above:

f: MEPS=2.93874e-39 1/MEPS=3.40282e+38 1/(MEPS--)=inf
d: MEPS=5.56268e-309 1/MEPS=1.79769e+308 1/(MEPS--)=inf
e: MEPS=8.40526e-4933 1/MEPS=1.18973e+4932 1/(MEPS--)=inf
查看更多
Viruses.
3楼-- · 2019-07-21 11:57

Here is a starting point to answer your question. I have simply divided by 2. Once you get to dividing by 2^^148, you come pretty close. You could then iteratively move closer and print out the hex representation of the number to see what the compiler is doing:

#include <iostream>
#include <stdio.h>


#include <limits>//is it here?

int main() {
    double d_eps,invd_eps;
    float f_eps,invf_eps;
    invf_eps = 1.f/f_eps;//invf_eps should be finite
    float last_seed = 0;
    float seed = 1.0;
    for(int i = 0; i < 1000000; i++) {
        last_seed = seed;
        seed = seed/2;
        if(seed/2 == invd_eps) {
            printf("Breaking at i = %d\n", i);
            printf("Seed:  %g, last seed: %g\n", seed, last_seed);
            break;
        }
    }

    printf("%f, %lf, %f, %lf\n\n", f_eps, d_eps, invf_eps, invd_eps);
    return 0;
}

Output:

Breaking at i = 148
Seed:  1.4013e-45, last seed: 2.8026e-45
0.000000, 0.000000, inf, 0.000000


Process finished with exit code 0
查看更多
登录 后发表回答