Can a conversion from double to int be written in portable C

前端 未结 7 761
借酒劲吻你
借酒劲吻你 2020-12-10 01:42

I need to write function like double_to_int(double val, int *err) which would covert double val to integer when it\'s possible; otherwise report an error (NAN/I

7条回答
  •  旧时难觅i
    2020-12-10 02:23

    Can a conversion from double to int be written in portable C (?)

    is there any way to implement double_to_int function in cross-platform way (basing only on C standard, even not considering target platforms to support IEEE-754).?

    int double_to_int(double val, int *err)
    

    Detail: (int)val truncates the fractional portion, so the range of convertible val using (int)val is mathematically:
    INT_MIN - 0.9999... ≤ val ≤ INT_MAX + 0.9999... or
    INT_MIN - 1 < val < INT_MAX + 1.


    Yes a cross-platform way, by using exact floating-point math and constants, code can test for conversion success.

    2.0*(INT_MAX/2+1) is certainly exactly converted to a FP constant.

    val - INT_MIN > -1.0 is akin to val > INT_MIN - 1.0 but does not suffer imprecision (with the common 2's complement machines) possible with INT_MIN - 1.0. Recall that the integer type may have greater precision than double. Consider a 64-bit int and INT_MIN - 1.0 not exactly representable as a double.

    Code does not use (double)INT_MAX which also may be imprecise.


    To copy myself:

    #include 
    #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 val, int *err) {
      if (val < DBL_INT_MAXP1) {
        #if -INT_MAX == INT_MIN
        // rare non-2's complement machine 
        if (val > DBL_INT_MINM1) {
          *err = OK;
          return (int) val;
        }
        #else
        if (val - INT_MIN > -1.0) {
          *err = OK;
          return (int) val;
        }
        #endif 
        // Underflow
        *err = ERR_MINUS_INF;
        return INT_MIN;
      }
      if (x > 0) {
        // Overflow
        *err = ERR_PLUS_INF;
        return INT_MAX;
      }
      // NaN;
      *err = ERR_NAN;
      return 0;
    }
    

    Corner weakness: FLT == 10 and the integer type > 34 bits.

提交回复
热议问题