为什么从 int 转换为 float 值?

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

我正在阅读 CS:APP,关于转换,它说当将 从 int 转换为 float 时,数字不能溢出,但它可能会被四舍五入。

这对我来说似乎很奇怪,因为我不知道要舍入什么,所以我已经试过了。我认为只有非常大的整数(接近 INT_MAX/INT_MIN)才会出现这种情况,但四舍五入也发生在大约一亿的值上。 (不确定首先发生这种情况的确切位置)。

为什么会这样? float的范围远远超过int的范围。有人可能会说浮点数不能精确表示,但是从 int 转换为 double 时,值没有变化。 double 优于 float 的优点是它具有更大的范围和精度。但是 float 仍然有足够的范围到 "encapsulate" 整数,精度不应该真正重要,因为整数没有小数位(好吧,全是 0),或者我想错了?

这是我得到的一些输出(这里是代码: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  

使用 32 位 IEEE-754 表示实现的典型 float 只有 24 位有效数字,允许大约 7 位十进制数字的精度。因此,一旦达到数百万 (224 约 16M),您就会看到四舍五入。

(对于double,有效数有53位,253 约9×1015。 )

我假设 float 是指 32 位 IEEE-754 二进制浮点值,double 是指 64 位 IEEE-754 二进制浮点值, int 是指 32 位整数。

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

是的,但是float精度只有7-9位小数。更具体地说,有效数字只有 24 位宽...所以如果你试图在其中存储 32 位信息,你就会遇到问题。

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

当然可以,因为 double 有一个 53 位有效数字 - 那里有足够的空间容纳 32 位整数!

换句话说,连续 int 值之间的差距始终为 1...而连续 float 值之间的差距开始非常非常小...但随着值的大小增加。它在您达到 int 的限制之前就达到了 "more than 2"... 所以您进入了并非每个 int 都可以准确表示的阶段。

想起来另一种方式,你可以简单地使用pigeon-hole principle...甚至忽略NaN值,最多可以有 232 float 个值,其中至少有一个不是 int 的精确值 - 例如,取 0.5。有 232 int 个值,因此至少有一个 int 值没有精确的 float 表示。