hochan
hochan

Reputation: 221

Proper way to fit int overflow in c, when we cast int to float to int

#include <iostream>

int main() {
    int  num = 2147483647;
    std::cout << (int)(float)num << std::endl; 

    return 0;
}
./main
-2147483648
-2147483648

I know that a float to int conversion is safe, but an int to float conversion is not. I also know that real floating point cannot be expressed accurately. It seems very dangerous to see overflows even though the maximum value(except inf) of int is not exceeded.

I want to be safe when converting int to float or float to int no matter what arbitrary number comes in.

Which way is best to handle it? Also, what other exceptions should I consider?


The above question isn't clear and doesn't fit the stackoverflow question, so I'll fix it specifically.

Numbers in normal categories like 2147483647 also overflow. What range should I handle?

Upvotes: 1

Views: 1317

Answers (1)

chux
chux

Reputation: 153457

I know that a float to int conversion is safe, but an int to float conversion is not.

Each conversion has issues.

(Assume 32-bit int and 32-bit float for discussion.)

Large int to float risks lost of precision as float does not exactly encode all int. With OP's int num = 2147483647; (float)num, the 2147483647 was converted to 1 of 2 nearby float. With round to the nearest rounding mode, float: result was certainly 2147483648.0.

float to int truncates any fraction. Conversion from infinity and Not-a-number pose addition concerns.

float to int risks implementation-defined behavior when the the floating point value is not inside the -2,147,483,648.9999... 2,147,483,647.9999... range. This is the case with OP's int num = 2147483647; (int)(float)num attempting to convert an out of range 2147483648.0 to int. In OP's case, the value was apparently wrapped around (232 subtracted) to end with -2147483648.


Which way is best to handle it? Also, what other exceptions should I consider?

With conversion int to float, expect rounding for large int.

With conversion float to int, expect truncation and perhaps test if value is in range.

With 2's complement integer encoding: a test to prevent out of range conversion.

#define FLT_INT_MAX_PLUS1 ((INT_MAX/2 + 1)*2.0f)

// return true when OK to convert 
bool float_to_int_test(float x) {
  return (x < FLT_INT_MAX_PLUS1) && (x - INT_MIN > -1.0f);
}

Other tests could be had to determine rounding or truncation.

Upvotes: 3

Related Questions