Why does a cast from int to float round the value?

I'm reading CS:APP, and regarding casts it says that when casting from int to float, the number cannot overflow, but it may be rounded.

It seemed odd to me as I didn't know what there was to round, so I've tried it out. I thought that this would only be the case for very large integers (near INT_MAX/INT_MIN), but rounding happens at values around a hundred million as well. (Not sure where exactly this happens first).

Why does this happen? The range of float far exceeds that of int. One might say that floating point numbers cannot be represented exactly, but when converting from intto double there is no change in value. The advantage of doubleover float is that it has greater range and precision. But floatstill has enough range to "encapsulate" integers, and precision shouldn't really matter as integers have no decimal places (well, all 0), or am I thinking wrong?

Here's some output that I got (here is the code: http://pastebin.com/K3E3A6Ni):

FLT_MAX = 340282346638528859811704183484516925440.000000  
INT_MAX     = 2147483647  
(float)INT_MAX = 2147483648.000000  
(double)INT_MAX = 2147483647.000000  
INT_MIN     = -2147483648  
(float)INT_MIN = -2147483648.000000  

====other values close to INT_MIN INT_MAX====  
INT_MAX-1     = 2147483646  
(float)INT_MAX-1 = 2147483648.000000  
INT_MIN+1     = -2147483647  
(float)INT_MIN+1 = -2147483648.000000  
INT_MAX-2      = 2147483645  
(float)INT_MAX-2  = 2147483648.000000  
INT_MAX-10     = 2147483637  
(float)INT_MAX-10 = 2147483648.000000  
INT_MAX-100         = 2147483547  
(float)INT_MAX-100  = 2147483520.000000  
INT_MAX-1000         = 2147482647  
(float)INT_MAX-1000 = 2147482624.000000  

(float)1.234.567.809 = 1234567808.000000  
(float)1.234.567.800 = 1234567808.000000  
(float)1.000.000.005 = 1000000000.000000  
(float)800.000.003   = 800000000.000000  
(float)500.000.007   = 500000000.000000  
(float)100.000.009   = 100000008.000000  
Jon Skeet
people
quotationmark

I'm assuming that by float you mean a 32-bit IEEE-754 binary floating point value, by double you mean a 64-bit IEEE-754 binary floating point value, and by int you mean a 32-bit integer.

Why does this happen? The range of float far exceeds that of int

Yes, but the precision of float is only 7-9 decimal digits. To be more specific, the significand is only 24 bits wide... so if you're trying to store 32 bits of information in there, you're going to have problems.

but when converting from int to double there is no change in value

Sure, because a double has a 53-bit significand - plenty of room for a 32-bit integer there!

To think of it another way, the gap between consecutive int values is always 1... whereas the gap between consecutive float values starts very, very small... but increases as the magnitude of the value increases. It gets to "more than 2" well before you hit the limit of int... so you get to the stage where not every int can be exactly represented.

To think of it another way, you can simply use the pigeon-hole principle... even ignoring NaN values, there can be at most 232 float values, and at least one of those is not the exact value of an int - take 0.5, for example. There are 232 int values, therefore at least one int value doesn't have an exact float representation.

people

See more on this question at Stackoverflow