OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 6363|回复: 10

关于浮点类型数据精度损失的问题

[复制链接]

48

主题

537

帖子

2

精华

金牌会员

Rank: 6Rank: 6

积分
1369
金钱
1369
注册时间
2014-2-13
在线时间
169 小时
发表于 2016-3-17 09:49:54 | 显示全部楼层 |阅读模式
10金钱
QQ图片20160317094510.png
我理解的浮点数精度在存储的时候才会有损耗,当然不同类型数据转换的时候也会产生损耗。
那么上面的结果,第一个,把一个浮点数以float型存入计算机,为什么没有损耗?而第二个,计算时却产生了损耗?

最佳答案

查看完整内容[请看2#楼]

建议楼主参考下IEEE浮点格式的具体内容,里面有详细说明
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

15

主题

184

帖子

0

精华

高级会员

Rank: 4

积分
647
金钱
647
注册时间
2014-4-29
在线时间
299 小时
发表于 2016-3-17 09:49:55 | 显示全部楼层
建议楼主参考下IEEE浮点格式的具体内容,里面有详细说明
回复

使用道具 举报

2

主题

239

帖子

0

精华

高级会员

Rank: 4

积分
545
金钱
545
注册时间
2015-6-5
在线时间
110 小时
发表于 2016-3-17 11:34:25 | 显示全部楼层
你自己把他強制轉型成INT
犯啥傻阿...
回复

使用道具 举报

48

主题

537

帖子

2

精华

金牌会员

Rank: 6Rank: 6

积分
1369
金钱
1369
注册时间
2014-2-13
在线时间
169 小时
 楼主| 发表于 2016-3-17 12:52:52 | 显示全部楼层
本帖最后由 solo 于 2016-3-17 12:54 编辑
Rocks 发表于 2016-3-17 11:34
你自己把他強制轉型成INT
犯啥傻阿...

可能你理解错了,我说的是第一行打印的结果。第3行的是为了消除精度损耗带来的影响
回复

使用道具 举报

34

主题

805

帖子

4

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
1865
金钱
1865
注册时间
2011-3-29
在线时间
140 小时
发表于 2016-3-17 13:23:45 来自手机 | 显示全部楼层
浮点数存储也是以二进制存储的,会不会损耗得看十进制的数据能否精确的转换为二进制。
回复

使用道具 举报

6

主题

1097

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
3571
金钱
3571
注册时间
2014-12-2
在线时间
365 小时
发表于 2016-3-17 13:30:27 | 显示全部楼层
实力放图:

3.png


-----不正经的分割线----

z (38).jpg
坚决不用寄存器,拒绝重复造轮子。
回复

使用道具 举报

6

主题

1097

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
3571
金钱
3571
注册时间
2014-12-2
在线时间
365 小时
发表于 2016-3-17 13:36:10 | 显示全部楼层
本帖最后由 xkwy 于 2016-3-17 13:38 编辑

0.4连乘2不能消除小数,所以不能精确保存。

因此,11.4在写入a时就已经有精度损失了。

你对此并没有理解深刻,你难道以为打印出的是11.400000就是11.400000吗?
把float转成double不会有精度损失,让你看看你看到的11.400000的真面目:

4.png
坚决不用寄存器,拒绝重复造轮子。
回复

使用道具 举报

48

主题

537

帖子

2

精华

金牌会员

Rank: 6Rank: 6

积分
1369
金钱
1369
注册时间
2014-2-13
在线时间
169 小时
 楼主| 发表于 2016-3-17 16:14:49 | 显示全部楼层
xkwy 发表于 2016-3-17 13:36
0.4连乘2不能消除小数,所以不能精确保存。

因此,11.4在写入a时就已经有精度损失了。

之所以举11.4的例子是因为我知道它转成二进制时小数部分是无限的。我想验证在此时它的损耗,却被打印的结果迷惑了。为什么应该被截断的数据打印出来的结果和原数据一点不差?
回复

使用道具 举报

48

主题

537

帖子

2

精华

金牌会员

Rank: 6Rank: 6

积分
1369
金钱
1369
注册时间
2014-2-13
在线时间
169 小时
 楼主| 发表于 2016-3-18 13:00:07 | 显示全部楼层
本帖最后由 solo 于 2016-3-18 13:05 编辑

感觉大家也没深入考虑这个问题,我就把数据验算一下吧。
1、float数据转二进制源数据:11.4
float型数据32位长度:   符号   阶码  尾数
                                1位     8位   23位
①整数位转二进制
十进制:11
二进制:1011

②小数位转二进制
十进制:0.4
二进制:
0.4X2 = 0.8; 取0
0.8X2 = 1.6; 取1
0.6X2 = 1.2; 取1
0.2X2 = 0.4; 取0
0.4X2 = 0.8; 取0
0.8X2 = 1.6; 取1
0.6X2 = 1.2; 取1
0.2X2 = 0.4; 取0
.......
无限循环。。。只有出现0.5才能结束,可惜这种数据占少数。所以浮点型数据在计算机里的存储是有损存储。

③组合尾数
整数位+小数位(阶码只有23位,整数位全取,小数位截取)
1011. 0110 0110 0110 0110 0110
小数点左移3位:
1.011 0110 0110 0110 0110 0110
IEEE 754-2008默认最左边的“1”是缺省的,去掉最左边的1:
011 0110 0110 0110 0110 0110 (阶码)

④阶码
3+127 = 130;小数点左移的位数(3)+127
所以,阶码是:1000 0010

最后,11.4的存储格式:
二进制:
QQ图片20160318125720.png
十六进制:
0x41 36 66 66

验证:
QQ图片20160318125919.png
2、二进制数据转float
逆推的过程就不打了,我算出的结果是11.399993896484375,float的有效位数只有6~7位,所以最后的数据取11.39999。
以上说明11.4存入计算机的有损耗的,但是为啥printf打印出来的确实11.4呢?怀疑printf有进位处理。



回复

使用道具 举报

48

主题

537

帖子

2

精华

金牌会员

Rank: 6Rank: 6

积分
1369
金钱
1369
注册时间
2014-2-13
在线时间
169 小时
 楼主| 发表于 2016-3-18 13:07:51 | 显示全部楼层
二楼不是我想要的答案,可惜现在没有那个权限修改了,而且设了答案也不能编辑了。。。
回复

使用道具 举报

15

主题

184

帖子

0

精华

高级会员

Rank: 4

积分
647
金钱
647
注册时间
2014-4-29
在线时间
299 小时
发表于 2016-3-18 16:09:59 | 显示全部楼层
solo 发表于 2016-3-18 13:00
感觉大家也没深入考虑这个问题,我就把数据验算一下吧。
1、float数据转二进制源数据:11.4
float型数据3 ...

浮点数存储不会产生丢失精度,估计你想说的意思是编译时产生的精度丢失吧,字符串变成浮点会有精度丢失。printf函数因为不开源,外人也不知道有没有舍入,不过看起来应该是有
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-20 01:27

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表