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 int
to double
there is no change in value. The advantage of double
over float
is that it has greater range and precision. But float
still 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
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.
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.
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.
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.
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
todouble
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.
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.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With