Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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  
like image 799
Beko Avatar asked Feb 04 '15 15:02

Beko


People also ask

Does casting to int round up or down?

For example: double pi = 3.14159; int x = int (pi); The int function returns an integer, so x gets the value 3. Converting to an integer always rounds down, even if the fraction part is 0.99999999.

What will happen if you cast a float to an integer?

Since a float is bigger than int, you can convert a float to an int by simply down-casting it e.g. (int) 4.0f will give you integer 4. By the way, you must remember that typecasting just get rid of anything after the decimal point, they don't perform any rounding or flooring operation on the value.

Does int () always round down?

Notes. INT is not equivalent to ROUNDDOWN with places set to 0 . INT rounds down using value, whereas ROUNDDOWN rounds down using absolute value, which causes differences for negative values of value . INT is also not equivalent to FLOOR with significance -1 for negative values of value for the same reason as above.

Does int casting round up or down Java?

Integer arithmetic always rounds down (towards zero). If you look at the documentation, those methods that you use take floating point. You can't round() or ceil() a number, when it is always a whole number. If you want to control rounding, I would suggest that you convert to floating point before you do the operation.


2 Answers

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 232float values, and at least one of those is not the exact value of an int - take 0.5, for example. There are 232int values, therefore at least one int value doesn't have an exact float representation.

like image 118
Jon Skeet Avatar answered Oct 20 '22 08:10

Jon Skeet


A typical float that is implemented with the 32-bit IEEE-754 representation has only 24 bits for the significand, which allows for about 7 decimal digits of precision. So you'll see rounding as soon as you hit the millions (224 ≈ 16M).

(For a double, the significand has 53 bits, and 253 ≈ 9×1015.)

like image 7
Kerrek SB Avatar answered Oct 20 '22 10:10

Kerrek SB