如下:

float a = 0.65f;
float b = 0.6f;
float c = a - b;

此时c为多少?

0.05?错误!

此时c为0.0499999523!

为什么?

其根本原因是计算机所使用二进制01代码无法准确表示某些带小数位的十进制数据。

下面我们来分析下:

我们知道将一个十进制数值转换为二进制数值,需要通过下面的计算方法:

1. 整数部分:连续用该整数除以2,取余数,然后商再除以2,直到商等于0为止。然后把得到的各个余数按相反的顺序排列。简称"除2取余法"。

2. 小数部分:十进制小数转换为二进制小数,采用"乘2取整,顺序排列"法。用2乘以十进制小数,将得到的整数部分取出,再用2乘余下的小数部分,然后再将积 的整数部分取出,如此进行,直到积中的小数部分为0或者达到所要求的精度为止。然后把取出的整数部分按顺序排列起来,即先取出的整数部分作为二进制小数的 高位,后取出的整数部分作为低位有效位。简称"乘2取整法"。

3. 含有小数的十进制数转换成二进制,整数、小数部分分别进行转换,然后相加。

例如:将十进制数值25.75转换为二进制数值,步骤如下:

25(整数部分)

25/2=12......1

12/2=6.......0

6/2=3......0

3/2=1......1

1/2=0......1

(25) 10=(11001) 2

0.75(小数部分)

0.75*2=1.5......1

0.5*2=1......1

(0.75) 10=(0.11) 2

(25.75) 10=(11001) 2+(0.11) 2=(11001.11) 2

按照上述方法,我们将0.65及0.6转换为二进制代码:

(0.65)10 = (0.101001100110011001100110011001100110011......)2

(0.6) 10 = (0.10011001100110011001100110011001100110011......)2

后面的省略号表示已经算不完了,后面在无限重复 0011 这段二进制数值。

文章开始部分,我们用的float类型,下面我们来看看float类型是否能存储上面转换出的二进制代码。

目前计算机上存储浮点数值是按照IEEE(电气和电子工程师协会)754浮点存储格式标准来存储的。

IEEE单精度浮点格式共32位,包含三个构成字段:23位小数f,8位偏置指数e,1位符号s。将这些字段连续存放在一个32位字里,并对其进行编码。其中0:22位包含23位的小数f; 23:30位包含8位指数e;第31位包含符号s。如下图所示:

也就是说上面将0.65及0.5转换出的二进制代码,我们只能存储23位,即使数据类型为double,也只能存储52位,这样大家便能看出问题出现的原因了。

截取的二进制代码已无法正确表示0.65及0.5,根据这个二进制代码肯定无法正确得到结果0.05。

如何解决这个问题?知道其根本原因后,我们知道是无法从根本上解决这个问题的,但我们可以有一些曲线救国的方法,下面列举几个:

1. 因为二进制数值可以准确表示整数(可以使用整数转换为二进制方法验证下),所以可以将小数乘以10或100等变成整数,然后做运算,最后再通过除以10或100等获得结果;

2. 通过截取结果的有效小数位数等,来取得最好的近似结果,然后在做处理。

3. 对于可以用有限长度的二进制数值表示的十进制数值,可以使用存储位数大于其长度的数据类型。

解决方案正在补充中……,若各位有什么好的方法也可以提出来!

以上解决方案需要按照使用的实际情况来决定使用哪种方法。

来源:http://www.2cto.com/kf/201007/52889.html

PHP浮点运算结果出现误差原因分析及解决方案相关推荐

  1. Android Bitmap转换WebP图片导致损坏的分析及解决方案

    Android Bitmap转换WebP图片导致损坏的分析及解决方案 参考文章: (1)Android Bitmap转换WebP图片导致损坏的分析及解决方案 (2)https://www.cnblog ...

  2. C#/.NET基于Topshelf创建Windows服务的守护程序作为服务启动的客户端桌面程序不显示UI界面的问题分析和解决方案

    C#/.NET基于Topshelf创建Windows服务的守护程序作为服务启动的客户端桌面程序不显示UI界面的问题分析和解决方案 参考文章: (1)C#/.NET基于Topshelf创建Windows ...

  3. AppStore IPv6-only审核被拒原因分析及解决方案-b

    AppStore IPv6-only审核被拒原因分析及解决方案-b 参考文章: (1)AppStore IPv6-only审核被拒原因分析及解决方案-b (2)https://www.cnblogs. ...

  4. linux系统脚本安装失败,ubuntu16.04下vim安装失败的原因分析及解决方案

    先给大家说下问题描述? 重装了ubuntu系统,安装vim出现了以下问题: sudo apt-get install vim 正在读取软件包列表... 完成 正在分析软件包的依赖关系树 正在读取状态信 ...

  5. android系统性能优化(63)---Android APP 卡顿问题分析及解决方案

    Android APP 卡顿问题分析及解决方案 用户对卡顿的感知, 主要来源于界面的刷新. 而界面的性能主要是依赖于设备的UI渲染性能. 如果我们的UI设计过于复杂, 或是实现不够友好,计算绘制算法不 ...

  6. MYSQL主从不同步延迟原理分析及解决方案

    MYSQL主从不同步延迟原理分析及解决方案 参考文章: (1)MYSQL主从不同步延迟原理分析及解决方案 (2)https://www.cnblogs.com/shishanyu/p/7977835. ...

  7. spring多数据源分布式事务的分析与解决方案

    spring多数据源分布式事务的分析与解决方案 参考文章: (1)spring多数据源分布式事务的分析与解决方案 (2)https://www.cnblogs.com/qianjun2017/p/83 ...

  8. Selenium常见异常分析及解决方案

    Selenium常见异常分析及解决方案 参考文章: (1)Selenium常见异常分析及解决方案 (2)https://www.cnblogs.com/superhin/p/11454861.html ...

  9. 本机未装Oracle数据库时Navicat for Oracle 报错:Cannot create oci environment 原因分析及解决方案

    本机未装Oracle数据库时Navicat for Oracle 报错:Cannot create oci environment 原因分析及解决方案 参考文章: (1)本机未装Oracle数据库时N ...

最新文章

  1. 网站前端和后台性能优化18
  2. php变量名当文件命_php基础教程 第二步 通俗易懂的学习变量、常量与数据类型...
  3. 用window.location.href实现刷新另个框架页面
  4. python核心模块之pickle和cPickle讲解
  5. Oracle入门(十二I)之误删除数据的恢复方法
  6. 数的划分(洛谷-P1025)
  7. 【Shell 编程基础第一部分】Shell脚本HelloShell及简单的Shell基础
  8. C/C++ 随机数生成器的 随机化
  9. ListView 搜索函数
  10. 在字符串中标红_在C ++中标记字符串
  11. 参观 Facebook 是一种什么体验?
  12. mac下用mysql执行sql文件完整
  13. 爬取《战狼2》电影短评论,生成图云
  14. MySQL 是如何保证一致性、原子性和持久性的
  15. vga转HDMI与hdmi转VGA区别
  16. 作业 20180925-4 单元测试,结对
  17. canvas-球体动画运动
  18. CMWAP 和 CMNET 的主要区别与适用范围
  19. REDIS缓存集群介绍
  20. Grasshopper 二次开发 (C#) Part 3 - Write Simple Plug-in for Grasshopper in Visual Studio

热门文章

  1. 细胞(信息学奥赛一本通-T1329)
  2. 9 WM配置-主数据-定义物料分阶段的范围(Staging Area)
  3. 38 MM配置-采购-采购订单-采购订单审批-定义采购订单审批过程
  4. c++基础语句(条件判断)
  5. 取某个字段的前几位 php,php如何实现截取前几个字符
  6. python怎么另起一行阅读答案_一行代码将Pandas加速4倍
  7. numpy 数组访问方式_索引、切片、迭代
  8. latex中空一整行,新的一行顶格写
  9. 时间戳timestamp
  10. 华为服务器存储系列,华为 服务器 存储相关资料(示例代码)