【Python基础】为何0.1+0.2≠0.3,使用Python程序深入理解计算机浮点数的运算

用过Python这门编程语言的应该都会发现,当我们输入0.1+0.2时,打印出来的却不是0.3,而是0.30000000000000004。

那么这是为什么呢?其实不仅是Python,很多编程语言例如C、Java、JavaScript等等都有这种特性

Java:

原理很简单,所有数的运算在计算机中都是进行二进制计算的,十进制小数也是一样,十进制小数在进行运算时首先将十进制数转换成二进制数之后再进行运算,运算结果又转换成十进制并显示出来。

1、IEEE 754规范

所有浮点数在进行运算时都需要遵循IEEE 754规范,IEEE 754浮点数表示方法规定浮点数的两种转化方式:

  1. 单精度浮点数(float):1位符号位+8位指数位+23位尾数位
  2. 双精度浮点数(double):1位符号位+11位符号位+52位尾数位

其中符号位用来表示正负,指数位限制数的范围,尾数位限制数的精度。这也就是说,当采用float类型表示浮点数时,能表示二进制的范围是+(8位指数).(23位小数)~-(8位指数).(23位小数),所以在把十进制小数0.1转化成二进制小数时得到的是一个超出能表示二进制小数最大尾数的小数并且是无限小数,但因为表示的范围有限,仅保留前23位小数,也就导致了精度缺失。不过在一些编程语言中,为了更好的表示十进制小数,默认采用的是将十进制小数保留16位。

2、应用Python程序深入理解计算机二进制浮点数的运算

十进制小数转换成二进制的方法,如果需要把十进制小数转换成二进制,一般的方法是先将整数转化成二进制数得到二进制小数的整数部分,再将十进制小数的小数部分乘以2取整数部分直至尾数为0,得到的整数顺序排列即为该十进制小数的二进制小数部分。例如十进制数0.5=0.+floor(0.5*2)=二进制数0.1

由于bin函数不能将十进制小数转换成二进制,所以我在Python中根据十进制小数转换二进制规则来设计一个函数dec_to_binf,函数非常简单

from math import floordef dec_to_binf(dec_num, precision):result = "0."for i in range(precision):# 取整数部分integer = floor(dec_num * 2)# 取小数部分,为了防止运算过程中精度再次缺失陷入死循环,用round保留12位小数,避免像0.30000000000000004的情况出现dec_num = round(dec_num, 12) * 2 - integerresult = result + str(integer)return result

因为在二进制数中有尾数精度缺失,不能直接表示成二进制数,所以我让它们最后都返回字符串类型。传入参数dec_num为1以内的十进制小数,precision为保留的二进制精确度。

一切准备就绪,让我们回到主题,当0.1+0.2时计算机内部情况到底是怎样的。

程序如下:

所有二进制数均保留80位小数,转化后结果为

十进制数0.1=二进制数0.0001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001

十进制数0.2=二进制数0.0011 0011 0011 0011 0011 0011 0011 0011 0011 0011 0011 0011 0011 0011 0011 0011 0011 0011 0011 0011

可以发现它们是一个无限循环小数,都超过了double类型所能表示的最大尾数位数52位,后面我更据IEEE 754规范将它们保留52位小数(遵循逢1进1,遇0舍弃)

利用二进制数的加法运算可以算出 十进制数0.1 + 十进制数0.2 = 二进制数0.0100 1100 1100 1100 1100 1100 1100 1100 1100 1100 1100 1100 1101

再设计一个函数将二进制小数转换成十进制数,函数也很简单,原理是根据各位上的权来计算十进制数,比如二进制数0.1011=(1*2\^-1)+(0\*2\^-2)+(1\*2\^-3)+(1\*2\^-4)。函数如下:

def binf_to_dec(binf):sum_dec = 0# 仅计算0.后面尾数,偏移量为2for i in range(len(binf)-2):# 根据位上的权和系数来计算每一位的结果sum_dec = sum_dec + float(binf[i+2]) * 2**-(i+1)return sum_dec

传入参数binf是一个字符型二进制数,将前面计算的和传入运行如下:

可以看到结果和直接计算0.1+0.2的结果一致。而真正出现问题的步骤在将0.1和0.2的二进制循环小数保留52位尾数,这里出现了精度缺失。那么我们可以得出结论了,0.1+0.2≠0.3其实是由于进制转换过程中出现了精度缺失。

3、写在最后

无论在何种计算机中,都遵循IEEE 754标准,都会出现这种小数运算精度缺失的情况,而最好的解决办法就是避免使用小数来进行运算,尤其是对精度要求及其严格的军工、航天等领域。最后欢迎来访我的个人网站https://angie.js.cn/
文章来自https://www.angie.js.cn/index.php/archives/43.html

【Python基础】为何0.1+0.2≠0.3,使用Python程序深入理解计算浮点数的运算相关推荐

  1. ​【Python基础】告别枯燥,60 秒学会一个 Python 小例子(文末下载)

    本文推荐一个python的傻瓜式的学习资源,内容简单易懂,让人可以在60 秒学会一个 Python 小例子 当前库已有 300多 个实用的小例子 本文来源:https://github.com/jac ...

  2. python基础语法花多长时间_怎么自学python,大概要多久?

    2020年最后一天,还有一个多小时就是2021年了,先祝愿大家2021年都能够健康平安发大财! 自学Python的方法因人而异,而大概需要多久就更是各说各话了,但是自学Python的路径都是一致的:先 ...

  3. 【Python基础学习一】在OSX系统下搭建Python语言集成开发环境 附激活码

    Python是一门简单易学,功能强大的编程语言.它具有高效的高级数据结构和简单而有效的面向对象编程方法.Python优雅的语法和动态类型以及其解释性的性质,使它在许多领域和大多数平台成为编写脚本和快速 ...

  4. python基础教程第三版电子版百度云-《python基础教程第三版》高清版PDF免费下载...

    下载地址1:http://t.cn/EGxO1sW Python基础教程 第3版Python简明教程书籍 Python编程从入门到实践 灵程序设计丛书 <python基础教程第三版>高清版 ...

  5. python基础代码库-python3.4第三方库的安装?python基础代码库

    python怎么安装下载模块 python安装下载模块的:1.按盘上的[win r]快,打开运行窗口:2.输入cmd,点击定]:3.在打开的命令提示符中执行[pip install 模块名]命令即可. ...

  6. python基础语法+爬虫精进.pdf_风变编程《Python基础语法+爬虫精进》

    作为IT小白,从没想过会主动去学习这方面的知识,因为学历专业差距很大,从事职业也基本用不上这些.然而,在偶然一次机会接触了风变编程体验课后,我发现了python给我打开了一个新的视野,未知领域的探索就 ...

  7. python基础知识教学_【松勤教育】Python基础知识

    1.算法是什么? 定义:对如何完成一项任务的详尽描述.在编程中,算法即:计算机可以理解的语言,这类对机器友好的描述叫做程序,程序主要包含表达式和语句. 表达式:计算机程序的组成部分,用于表示值,表达式 ...

  8. python基础语言与应用第五章_《Python基础教程》 读书笔记 第五章(下)循环语句...

    5.5.1while循环 x=1 while x<=100: print x x+=1 确保用户输入了名字: name="" while not name: name=raw ...

  9. 学完python基础知识之后可以做些什么-学完Python基础知识后,你真的会python吗?...

    前言 最近觉得 Python 太"简单了",于是在师父川爷面前放肆了一把:"我觉得 Python 是世界上最简单的语言!".于是川爷嘴角闪过了一丝轻蔑的微笑(内 ...

最新文章

  1. 为什么Scrum模式适合软件开发?
  2. SAP EWM - 物料主数据 - EWM系统库存规划 - SLOTTING视图属性
  3. Spring Boot如何初始化数据
  4. python【数据结构与算法】选数问题(选不相连最大值——DP)
  5. ALEIDoc EDI(6)--Filter Conversion
  6. VTK修炼之道56:图形基本操作进阶_表面重建技术(三维点云曲面重建)
  7. androidstudio build tools安装_如何导入Android Studio(AS)项目
  8. (王道408考研操作系统)第四章文件管理-第一节2:文件的逻辑结构
  9. 如何让Excel单元格中的名字分散对齐
  10. (16)WEB前端开发规范之HTML规范
  11. 副法线和正切是什么?
  12. 16.2互联网媒体信息讽刺识别
  13. 05-2_部署 kube-apiserver 集群
  14. Java设计模式-代理模式
  15. 永中集成Office的春天能否到来?
  16. 爱心的数学函数方程_数学里有哪些可以示爱的图像?它们的函数方程又是什么?...
  17. 10 款富有创意的博客名片设计
  18. Android实现屏幕自动旋转功能
  19. C++笔记 char
  20. python如何将字典数据存入excel

热门文章

  1. wordpress如何修改后台登录地址
  2. CMD 命令速查手册
  3. 蓝桥杯 15决赛 B4 穿越雷区(bfs)
  4. Mysql进阶学习所用到的SQL测试库代码
  5. 市科技局举办消防安全知识讲座
  6. Codeforces 360A(找性质)
  7. 2021年幼儿园教师招聘:大班写生创作:中国石拱桥
  8. 雅腾php怎么样_浅谈PHP发展前景及就业
  9. 机器学习7:朴素贝叶斯
  10. 【React路由】编程式路由导航和withRouter的使用——push / replace