为啥从 int 转换为浮点值?

Posted

技术标签:

【中文标题】为啥从 int 转换为浮点值?【英文标题】:Why does a cast from int to float round the value?为什么从 int 转换为浮点值? 【发布时间】:2015-02-04 15:56:26 【问题描述】:

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

这对我来说似乎很奇怪,因为我不知道要舍入什么,所以我尝试了一下。我认为这只适用于非常大的整数(靠近INT_MAX/INT_MIN),但舍入也发生在大约一亿的值上。 (不确定首先发生在哪里)。

为什么会这样? float的范围远远超过int的范围。有人可能会说浮点数不能精确表示,但是当从int 转换为double 时,值没有变化。 doubleover float 的优势在于它具有更大的范围和精度。但是float仍然有足够的范围来“封装”整数,并且精度应该不重要,因为整数没有小数位(嗯,全为 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  

【问题讨论】:

趣事:2147483647.0f == 2147483648.0f @dmg 有趣的事实不取决于舍入模式吗? 浮点数通过否定证明了上帝的存在,因为它们显然是撒旦的作品。 :-) @Bob Jarvis Satire 不谈,The Father of Floating Point 和其他人进行了稳健、有效的长期 FP 设计。 【参考方案1】:

我假设float 表示 32 位 IEEE-754 二进制浮点值,double 表示 64 位 IEEE-754 二进制浮点值,int 表示表示一个 32 位整数。

为什么会这样? float的范围远远超过int的范围

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

但从int 转换为double 时,值没有变化

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

换一种说法,连续的int 值之间的差距始终为 1...而连续的float 值之间的差距开始时非常非常小...但随着值的大小增加而增加.在您达到int 的限制之前,它会达到“超过 2”...所以您进入了并非每个int 都可以精确表示的阶段。

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

【讨论】:

不知道鸽洞原理,但这就是我用外行的方式向自己解释为什么不是所有整数都可以用浮点数表示的原因。 我一直以为精度是指小数位数。例如,float 可能有 6,而 double 可能有 15。那么 7-9 十进制数字的精度究竟是什么意思? @Beko:这意味着 二进制 浮点值的精度有点难以指定 - 特别是在规范化发挥作用时。基本上,如果你依赖float超过7个,你就有麻烦了。【参考方案2】:

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

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

【讨论】:

以上是关于为啥从 int 转换为浮点值?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 int 被提升为 double 而不是 float 以进行隐式转换

将浮点向量转换为 16 位 int 而不饱和

如何将纬度和经度转换为莫顿码(z 阶曲线)

使用按位运算将 Int 转换为 Float 或将 Float 转换为 Int(软件浮点)

归一化整数到/从浮点转换

Delphi float浮点值转换整型int 方法