tags:

views:

199

answers:

6

I am getting a benign warning about possible data loss

warning C4244: 'argument' : conversion from 'const int' to 'float', possible loss of data

Question

I remember as if float has a larger precision than int. So how can data be lost if I convert from a smaller data type (int) to a larger data type (float)?

+10  A: 

Because float numbers are not precise. You cannot represent every possible value an int can hold into a float, even though the maximum value of a float is much higher.

For instance, run this simple program:

#include <stdio.h>

int main()
{
 for(int i = 0; i < 2147483647; i++)
 {
  float value = i;
  int ivalue = value;
  if(i != ivalue)
   printf("Integer %d is represented as %d in a float\n", i, ivalue);
 }
}

You'll quickly see that there are thousands billions of integers that can't be represented as floats. For instance, all integers between the range 16,777,219 and 16,777,221 are represented as 16,777,220.

EDIT again Running that program above indicates that there are 2,071,986,175 positive integers that cannot be represented precisely as floats. Which leaves you roughly with only 100 millions of positive integer that fit correctly into a float. This means only one integer out of 21 is right when you put it into a float.

I expect the numbers to be the same for the negative integers.

zneak
@BlueNovember: Every integer >2^24.
Stephen
Not thousands. Billions.
slacker
your code converts a float(bigger) to int(smaller) so i supporse there is possible data loss. My question is about int to float
Dr Deo
@Dr Deo: `i` is an integer that I then cast into a `float`. If precision was not lost, then casting it back to an integer would give the same number back. Which is not the case.
zneak
@Stephen:You already corrected 23->24, but still not *every*. Every positive even integer <= 2^25 is exactly representable in a `float`. Every positive integer divisible by 4 which is <= 2^26 is also.
slacker
@slacker: Thanks, good point.
Stephen
+1 interesting post (and comments)
RJFalconer
"Why make thousands when we could make... *billions*"
Robert Fraser
@Robert Fraser: yeah, I _seriously_ underestimated the number of integers that you can't fit into a `float`.
zneak
+6  A: 

On most architectures int and float are the same size, in that they have the same number of bits. However, in a float those bits are split between exponent and mantissa, meaning that there are actually fewer bits of precision in the float than the int. This is only likely to be a problem for larger integers, though.

On systems where an int is 32 bits, a double is usually 64 bits and so can exactly represent any int.

JSBangs
+4  A: 

Both types are composed of 4 bytes (32 bits). Only one of them allows a fraction (the float).

Take this for a float example;

34.156

(integer).(fraction)

Now use your logic; If one of them must save fraction information (after all it should represent a number) then it means that it has less bits for the integer part.

Thus, a float can represent a maximal integer number which is smaller than the int's type capability.

To be more specific, an "int" uses 32 bits to represent an integer number (maximal unsigned integer of 4,294,967,296). A "float" uses 23 bits to do so (maximal unsigned integer of 8,388,608).

That's why when you convert from int to float you might lose data.

Example: int = 1,158,354,125

You cannot store this number in a "float".

More information at:

http://en.wikipedia.org/wiki/Single_precision_floating-point_format

http://en.wikipedia.org/wiki/Integer_%28computer_science%29

Poni
This is slightly wrong for a few reasons. One of them being the `float` having 24 bits for mantissa, not 23. So every unsigned integer up to 16777216 is exactly representable.
slacker
how many bits does double use for the mantisa?
Dr Deo
The IEEE 754 single float has 23 bits of mantissa, which gives an effective range of 24 bits because the exponent is normalized. The mantissa "steals a bit" from the exponent.
Jive Dadson
@Dr Deo:`double` uses 53 bits for the mantissa.
slacker
A: 

A float is usually in the standard IEEE single-precision format. This means there are only 24 bits of precision in a float, while an int is likely to be 32-bit. So, if your int contains a number whose absolute value cannot fit in 24 bits, you are likely to have it rounded to the nearest representable number.

slacker
Nit: "Precision" has a standard meaning that is only coincidentally related to the range of the set of representable numbers. "Precision" is the smallest positive number that can be added to 1.0 and yield a number different from 1.0. The precision of an int is thus 1 (one bit, not 31 or 32). The precision of an IEEE 754 single float is approximately 5.96e-8 (24 bits).
Jive Dadson
@Jive Dadson:I used the word "precision" in a more casual (non-formal) way. In this answer it obviously meant "number of significant bits".
slacker
A: 

My stock answer to such questions is to read this - What Every Computer Scientist Should Know About Floating-Point Arithmetic.

Jim Buck
+1  A: 

Precision does not matter. The precision of int is 1, while the precision of a typical float (IEEE 754 single precision) is approximately 5.96e-8. What matters is the sets of numbers that the two formats can represent. If there are numbers that int can represent exactly that float cannot, then there is a possible loss of data.

Floats and ints are typically both 32 bits these days, but that's not guaranteed. Assuming it is the case on your machine, it follows that there must be int values that float cannot represent exactly, because there are obviously float values that int cannot represent exactly. The range of one format cannot be a proper super-set of the other if both formats use the same number of bits efficiently.

A 32 bit int effectively has 31 bits that code for the absolute value of the number. An IEEE 754 float effectively has only 24 bits that code for the mantissa (one implicit).

Jive Dadson