14

It's surprising for me to see that even when the value can be converted, an int to float conversion always give a warning. Why is this?

int i = 0;
float f = 0; // warning here

// I thought this was an implicit conversion,
// meaning it is convertible with no warnings.
f = i;      // another warning here

The warning is:

warning C4244: '=' : conversion from 'int' to 'float', possible loss of data
Keith Thompson
  • 254,901
  • 44
  • 429
  • 631
user103214
  • 3,478
  • 6
  • 26
  • 37
  • 1
    Assign MAX INT value to float type and see the result. – Prince John Wesley Oct 15 '11 at 01:21
  • 3
    float f = 0.0f; // 0 is integer. – Martin York Oct 15 '11 at 01:24
  • It gives same warning with both `f = MAXINT;` and `f = INT_MAX;` – user103214 Oct 15 '11 at 01:30
  • @John: I understand that `some_float = MAX_INT;` or `some_float = some_int` should give a warning. However, why would it be necessary for `0`? – ruslik Oct 15 '11 at 01:38
  • `float f = 0;` is ok. Since it's a constant value that can be represented exactly, there shouldn't be a warning for the implicit int-to-float conversion. But personally, I'd write `float f = 0.0;`, just to be more explicit. (And I'd probably use `double` unless there's a good reason to use `float`.) – Keith Thompson Oct 15 '11 at 01:41
  • @ruslik I think the warning is for the assignment `f = i;`, not for the initialization `float f = 0;`. The compiler doesn't necessarilyi know the value of `i`, so it assumes that there might be some loss of data. – Keith Thompson Oct 15 '11 at 01:42
  • @ruslik: Oops, I just saw the OP's comment on one of the answers. Apparently the compiler warns on both the initialization and the assignment. It's permitted to do so, but warning about the initializer is, um, less clever than it could be. – Keith Thompson Oct 15 '11 at 01:44
  • @KeithThompson: My thoughts exactly. I'm sure that 90% of such warnings are given for constants like `0` or `1`. And one single `if` in compiler could have them filtered out.. – ruslik Oct 15 '11 at 01:49

4 Answers4

14

It depends on how many bits you have in your int type. A float that is IEEE754 single precision is a 32-bit value but some of those bits are assigned to the exponent, meaning not all are available for precision.

If your int type has more precision than your float, then you may suffer loss of precision at the high end.

In other words, it may not be able to distinguish between INT_MAX and INT_MAX - 1.

Solution in that case is to use a wider floating point type (double) although, technically, you may find an implementation that has a 256-bit int type in which case you'll have to find another way :-)

This answer has a brief overview of how the floating point formats work, including the fact that only 23 of the 32 bits are available for the precision of the mantissa.

Community
  • 1
  • 1
paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
5

I answered a similar question here:

Why does GCC warn against this implicit conversion?

The reason is that an int needs to be rounded when it is casted into a float because float cannot contain all the precision of an int in this case.

In your case, a float only has about 24 bits of precision. While an int has 32 bits of precision, therefore, some precision is loss by this cast, hence the warning.

Community
  • 1
  • 1
Mysticial
  • 464,885
  • 45
  • 335
  • 332
  • There can be (and are) implementations where `float` can hold all values of type `int` without loss of information -- for example if `int` and `float` are 16 and 32 bits, respectively, or 32 and 64 bits. But compilers are of course free to use information about the particular implementation when deciding to issue a warning. – Keith Thompson Oct 15 '11 at 01:37
  • I do realize that, hence I've inserted "in this case" in my answer since it isn't defined to be universally true. – Mysticial Oct 15 '11 at 01:37
3

Just for fun, try this and see what the output is (hint, you would expect the numbers to all be the same, wouldn't you?):

int i1(INT_MAX), i2;

float f(i1);

i2 = f;

std::cout << i1 << ' ' << f << ' ' << i2 << '\n';

Well, the answers I get are:

2147483647 2.14748e+009 -2147483648

So the compiler is quite right to point out that something might go wrong with the cast, but it isn't clever enough to know for sure, because it will only tend to happen at the extremities of the numerical range. It's always best to static_cast<> in my view, for clarity at least, and to show the compiler that it was what you intended.

By the way I'm not entirely sure why the above result happens. Perhaps someone else can explain!

Robinson
  • 9,666
  • 16
  • 71
  • 115
  • It gives me two warnings, one on initializing float and one on converting to float. – user103214 Oct 15 '11 at 01:33
  • @user974191: That wasn't clear from your original question. I've updated it to reflect that information (though I'm a bit surprised it warned about `float f = 0;`). Please review my edits. – Keith Thompson Oct 15 '11 at 01:47
0

// I thought this was implicit conversion means it is covertible with no warnings?

No, that's not what it means. It just means that you can assign a value of one type to an object of another type without an explicit conversion (i.e., a cast), and the value will be converted implicitly.

And in this case, a warning could be appropriate. If int and float are both 32 bits (which is typical but not universal), then all values of type int are within the range of float, but there are many values of type int that cannot be represented exactly in type float.

The language standard requires at least one diagnostic message for any translation unit (source file) that violates a syntax rule or constraint. But compilers are free to issue any additional diagnostic that they like.

Keith Thompson
  • 254,901
  • 44
  • 429
  • 631
  • There is one important restriction on additional compiler diagnostics--the compiler cannot issue so many diagnostics as to render impossible the compilation of a standards-compliant program. There have been some compilers (don't know if there still are) which would die if one line produced too many warnings. While it would be unusual for one line to generate thousands of warnings, it would be possible for a standards-compilant program to do so with macro expansions. – supercat Nov 02 '11 at 14:38
  • @supercat: That applies equally to anything the compiler does, not just diagnostics. What you're describing is just a compiler bug; normally issuing umpteen gazillion warnings wouldn't cause a compiler to crash. And the standard permits compilers to fail due to capacity limits; it only requires it to translate and execute a *single* program that reaches all the specified limits (C99 5.2.4.1). – Keith Thompson Nov 02 '11 at 18:20