为什么float类型30000000.0f+3.0f的结果仍然是30000000.0f

1. 首先看问题结果

是不是结果还是 30000000.0f 而不是 30000003.0f

 

2. 分析原因

这是一个典型的大数吃小数问题,原因需要从浮点数的计算机实现说起

对于float,是4字节(强调下我这里讲的都是32位浮点数,其它位思想同样适用),共32个bit,那么怎么用这32位来表示float

首先最容易想到的是  浮点数的每位十进制数用4bit来表示,比如 999999.99 这样每个9用1001表示,那么在32bit上的布局是下面这样:  100110011001100110011001.10011001   这样的表示数据范围是 000000.00 ~ 999999.99 共大概1亿个数字,这种把小数点固定的方法就是 “定点小数”,这样表达简单易懂,但是有个缺点就是,明明32bit可以最多表示42亿个数字,现在只能表示1亿,太浪费了。

 

还有一个就是 “浮点小数” ,顾名思义,就是小数点会浮动,比如 99.5 你可以表示成 9.995 x 10^1,也可以

表示成0.9995 x 10^2, 小数点可以浮动必然需要引入指数,这就是我们学数学的时候说的科学计数法,但是这是10进制,二进制数同样适用,只是科学计数法的底数是2而已。对于浮点数的二进制表示 常规的是 IEEE-754标准(强调下我下面讲都是IEEE-754标准),回头我打算再写一篇博客专门介绍一下这个标准(可以到时候留意下我的博客更新),现在我们只需要知道,这套标准定义下的浮点数是把32位bit位,划分为3部分:

对于 30000000.0f,二进制浮点数表示如下: 

A = 0 10010111 11001001110000111000000  (依次是符号位1位  指数位8位  数字位23位)

对于 3.0f,二进制浮点数表示如下: 

B = 0 10000000 10000000000000000000000  (依次是符号位1位  指数位8位  数字位23位)

转换工具可参考 : https://www.h-schmidt.net/FloatConverter/IEEE754.html

 

现在就是 A + B  ,其中A和B的指数位和数字位均不同,CPU此时会把 A和B的指数位统一(向大数A的指数靠拢),这样只要 加 A和B的数字位就可以了,A和B的指数位相差23位,如果B的指数位要跟A一致,那么B的数字位就要整体向右移动23位,正好把B的数字部分

10000000000000000000000   第一个1溢出了,这就是为什么  30000000.0f + 3.0f 结果还是 30000000.0f的原因。

 

特别提醒下,IEEE754 的指数位表示的不是真实的指数值,而是有个映射关系:1~254(bit表示值,0和255有另外的作用) 映射到 -126~127(指数表示的真实值) 这 254 个有正有负的数上。如果我们把 32bit划分的3个部分分别表示为 s(符号位),e(指数位),f(数字位),那么没有参与映射的0和255有如下的作用:

下篇我在讲IEEE754标准的博客里会把这个也交代清楚

 

 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值