how do I make a portable isnan/isinf function

前端 未结 11 1498
遇见更好的自我
遇见更好的自我 2020-11-29 06:02

I\'ve been using isinf, isnan functions on Linux platforms which worked perfectly. But this didn\'t work on OS-X, so I decided to use std::is

11条回答
  •  日久生厌
    2020-11-29 06:28

    According to this, infinity is easy to check:

    • sign = either 0 or 1 bit indicating positive/negative infinity.
    • exponent = all 1 bits.
    • mantissa = all 0 bits.

    NaN is a bit more complicated because it doesn't have a unique representation:

    • sign = either 0 or 1.
    • exponent = all 1 bits.
    • mantissa = anything except all 0 bits (since all 0 bits represents infinity).

    Below is the code for double-precision floating-point case. Single-precision can be similarly written (recall that the exponent is 11-bits for doubles and 8-bits for singles):

    int isinf(double x)
    {
        union { uint64 u; double f; } ieee754;
        ieee754.f = x;
        return ( (unsigned)(ieee754.u >> 32) & 0x7fffffff ) == 0x7ff00000 &&
               ( (unsigned)ieee754.u == 0 );
    }
    
    int isnan(double x)
    {
        union { uint64 u; double f; } ieee754;
        ieee754.f = x;
        return ( (unsigned)(ieee754.u >> 32) & 0x7fffffff ) +
               ( (unsigned)ieee754.u != 0 ) > 0x7ff00000;
    }
    

    The implementation is pretty straightforward (I took those from the OpenCV header files). It uses a union over an equal-sized unsigned 64-bit integer which you might need to correctly declare:

    #if defined _MSC_VER
      typedef unsigned __int64 uint64;
    #else
      typedef uint64_t uint64;
    #endif
    

提交回复
热议问题