首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >简单加减运算为何还会出bug?

简单加减运算为何还会出bug?

作者头像
用户5521279
发布2019-09-05 18:46:06
8100
发布2019-09-05 18:46:06
举报
文章被收录于专栏:搜狗测试搜狗测试

最近输入法有用户反馈一个bug:v模式中数学运算结果不准确,7250.11-7249.68无法得到正确结果0.43

为了分析bug的由来,小编调研了浮点数在计算机中的存储和运算过程,接下来为大家分享7250.11-7249.68详细运算处理过程,解析结果0.429999999999的由来。

浮点数的存储

浮点数,顾名思义就是小数点位置可以浮动的数据,科学的规定浮点数常用公示表示:

其中N为浮点数,M为尾数,E为阶码(指数),R为阶的基数(计算机中R一般为2)。

类比十进制的科学计数法:12300 = 1.23 * 10^4,10为基数,4为指数,二进制中1.25 = 1.01 * 2^0,2为基数,0为指数,1.01为尾数。

基于以上基础,国际制定了IEEE 754标准规范完整定义了浮点数在计算机底层的存储方式。根据国际标准IEEEE 754,任意一个二进制浮点数N可以如下表示:

(1)S表示符号位,当S=0时,N为正数;当S=1时,N为负数;

(2)M表示尾数(二进制),值大于等于1且小于2;

(3)E表示指数。

单精度浮点数float类型数值在计算机中使用32bit存储,存储方式如下:

双精度浮点数double类型数值在计算机中使用64bit存储,存储方式如下:

在计算机内部存储尾数M时,M的范围总是[1,2),默认这个数的第一位总是1,可以被舍去,因此为了最大化利用这个空间,IEEE 754规定尾数部分只保存小数部分,所以float类型的尾数可以表示24位二进制,double类型的尾数可以表示53位二进制数。

根据IEEE 754标准,E指数部分是无符号整型数据,因此float类型E的取值范围为0~255,double类型的E的取值范围为0~2047。另外,在实际小数的二进制表示中,指数部分可能为负数,为了表示负数,IEEE 754规定,计算机中E部分实际存储的值为实际值加上中位值(float类型中位数为127,double类型中位数为1023)。

所以,float类型的数据,E用126表示-1,128表示1;double类型的数据,E用1021表示-2,1025表示2。

以上便是浮点数在计算机底层的存储过程。

浮点数转二进制

如何将一个浮点数转为符合IEEE 754标准的数据?

以float类型数3.22为例:

整数部分3:符号位为0,大小为11

小数部分0.22:

0.22 * 2 = 0.44 (0)

0.44 * 2 = 0.88 (0)

0.88 * 2 = 1.76 (1)

0.76 * 2 = 1.52 (1)

0.52 * 2 = 1.04 (1)

0.04 * 2 = 0.08 (0)

0.08 * 2 = 0.16 (0)

0.16 * 2 = 0.32 (0)

0.32 * 2 = 0.64 (0)

0.64 * 2 = 1.28 (1)

……

二进制表示为11.0011100001……,左移一位为1.10011100001……符合尾数部分规范

所以23位尾数10011100001010001111010

指数位:1 + 127 = 128(10000000)

最终二进制表示为01000000010011100001010001111010

计算机处理数学运算

以bug中的7250.11-7249.68运算为例,输入法中7250.11和7249.68使用的是双精度double类型存储,本文中以32bit存储为例说明:

(1)将7250.11和7249.68存储符合IEEE 754标准的二进制存储,分别为:7250.11(01000101111000101001000011100001)、7259.68(01000101111000101000110101110000)

(2)处理数据的指数位,保证运算数据的指数位相等,原则上指数低的数向指数高的数转换,本文中7250.11和7249.68的指数位相等,不需要转换。

(3)将尾数M相减,即1110 0010 1001 0000 1110 0001-1110 0010 1000 1101 0111 0000=000 0000 0000 0011 0111 0001,隐藏的24位为0。

(4)将结果转为符合IEEE 754标准的二进制数据,尾数左移14位,指数值-14,结果为0(S) 01111101(E) 10111000100000000000000(M),转换为10进制为0.43017578125

总结

在本次运算过程中共有两次精度损失:第一次是计算机存储浮点数时,第二次是标准化时,因此最终的结果并不完全准确。如果能够尽量降低精度损失,最终结果也会越接近真实数值,比如使用double类型存储运算7250.11-7249.68的结果为0.429999999999,更接近真实结果0.43。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-09-03,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 搜狗测试 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
对象存储
对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档