Handling overflow when casting doubles to integers in C

后端 未结 9 2038
耶瑟儿~
耶瑟儿~ 2020-12-09 08:24

Today, I noticed that when I cast a double that is greater than the maximum possible integer to an integer, I get -2147483648. Similarly, when I cast a double that is less

9条回答
  •  小蘑菇
    小蘑菇 (楼主)
    2020-12-09 09:10

    What is the best way to detect this under/overflow?

    Compare the truncated double to exact limits near INT_MIN,INT_MAX.

    The trick is to exactly convert limits based on INT_MIN,INT_MAX into double values. A double may not exactly represent INT_MAX as the number of bits in an int may exceed that floating point's precision. In that case, the conversion of INT_MAX to double suffers from rounding. The number after INT_MAX is a power-of-2 and is certainly representable as a double. 2.0*(INT_MAX/2 + 1) generates the whole number one greater than INT_MAX.

    The same applies to INT_MIN on non-2s-complement machines.

    INT_MAX is always a power-of-2 - 1.
    INT_MIN is always:
    -INT_MAX (not 2's complement) or
    -INT_MAX-1 (2's complement)

    int double_to_int(double x) {
      x = trunc(x);
      if (x >= 2.0*(INT_MAX/2 + 1)) Handle_Overflow();
      #if -INT_MAX == INT_MIN
      if (x <= 2.0*(INT_MIN/2 - 1)) Handle_Underflow();
      #else
      if (x < INT_MIN) Handle_Underflow();
      #endif
      return (int) x;
    }
    

    To detect NaN and not use trunc()

    #define DBL_INT_MAXP1 (2.0*(INT_MAX/2+1)) 
    #define DBL_INT_MINM1 (2.0*(INT_MIN/2-1)) 
    
    int double_to_int(double x) {
      if (x < DBL_INT_MAXP1) {
        #if -INT_MAX == INT_MIN
        if (x > DBL_INT_MINM1) {
          return (int) x;
        }
        #else
        if (ceil(x) >= INT_MIN) {
          return (int) x;
        }
        #endif 
        Handle_Underflow();
      } else if (x > 0) {
        Handle_Overflow();
      } else {
        Handle_NaN();
      }
    }
    

提交回复
热议问题