How to (portably) get DBL_EPSILON in C and C++

前端 未结 2 1282
忘了有多久
忘了有多久 2021-02-12 23:40

I am using GCC 3.4 on Linux (AS 3) and trying to figure out to get DBL_EPSILON, or at least a decent approximation. How can I get it programmatically?

相关标签:
2条回答
  • 2021-02-12 23:58

    It should be in "float.h". That is portable, it's part of the C and C++ standards (albeit deprecated in C++ - use <cfloat> or sbi's answer for "guaranteed" forward compatibility).

    If you don't have it, then since your doubles are IEEE 64-bit, you can just steal the value from someone else's float.h. Here's the first one I found:

    http://opensource.apple.com/source/gcc/gcc-937.2/float.h

    #define DBL_EPSILON 2.2204460492503131e-16

    The value looks about right to me, but if you want to be sure on your compiler, you could check that (1.0 + DBL_EPSILON) != 1.0 && (1.0 + DBL_EPSILON/2) == 1.0

    Edit: I'm not quite sure what you mean by "programmatically". It's a standard constant, you aren't supposed to calculate it, it's a property of the implementation given to you in a header file. But I guess you could do something like this. Again, assuming IEEE representation or something like it, so that DBL_EPSILON is bound to be whatever power of 0.5 represents a 1 in the last bit of precision of the representation of 1.0:

    double getDblEpsilon(void) {
        double d = 1;
        while (1.0 + d/2 != 1.0) {
            d = d/2;
        }
        return d;
    }
    

    Beware that depending on compiler settings, intermediate results might have higher precision than double, in which case you'd get a smaller result for d than DBL_EPSILON. Check your compiler manual, or find a way to force the value of 1.0 + d/2 to be stored and reloaded to an actual double object before you compare it to 1.0. Very roughly speaking, on PCs it depends on whether your compiler uses the x86 FPU instructions (higher precision), or newer x64 floating point ops (double precision).

    0 讨论(0)
  • 2021-02-13 00:05

    In C++ it's std::numeric_limits<double>::epsilon().

    0 讨论(0)
提交回复
热议问题