我和Python的Py交易》》》》》》 浮点数的身世字谜
什么是浮点数?
在数据类型中写道,浮点数是带小数点的小数,这个概念是不准确的;浮点数是除了无限不循环小数之外的小数,也就是可以用分数表示的带小数点的数。
好了,浮点数就这些内容,讲完了,各回各家,各找各妈。
不想回家的就继续往下看咯。。。
虽然浮点数中没有无限不循环小数但是有无限循环小数啊,计算机内存是有限的是怎么放下无限多个数的?
很简单啊,既然放不下这么多我就四舍五入一下把它变成可以放下的有限小数。
那这就涉及到的怎么对无限循环小数和超出计算机内存储存范围的有限小数进行四舍五入,在小数点后几位小数进行四舍五入。
我们就需要一个标准对上述等问题进行规范,已经有人给出了这个标准,IEEE给出了IEEE 754
IEEE和IEEE 754是什么东西?既然都这么问了,那就给出百度百科的链接好了。
n=0
for i in range(10):
n+=0.1
print(n) # 打印结果
# 0.1
# 0.2
# 0.30000000000000004
# 0.4
# 0.5
# 0.6
# 0.7
# 0.7999999999999999
# 0.8999999999999999
# 0.9999999999999999
不对啊,0.1是有限小数啊,不用四舍五入啊!干嘛会出现这样的鬼结果。
嘿嘿,这个怪我。
上文所说的的“计算机内存是有限的是怎么放下无限多个数的”’是我故意误导的,计算机储存信息是通过二进制数进行储存的,这个浮点数也要转换二进制才可以储存在计算机中,0.1的二进制表示是无限循环的。
所以舍入操作针对的是浮点数转换的二进制数,且舍入的规则也就变成了0舍1入,IEEE 754 中文叫做IEEE二进位浮点数算术标准。
在这也顺带科普一下,小数如何转换为二进制数。
是不是很爽,原来浮点数就是这么被放的计算机里面去的,那你又错了。
二进制小数里的小数点怎么存进计算机的内存中?(计算机储存数据都是用二进制来表达)
爽不爽,是不是有我的冲动,嘿嘿。解决方法也在IEEE 754中
IEEE 754 中规定了四种表示浮点数值的方式:单精确度(32位比特储存浮点数)、双精确度(64位比特储存浮点数)、延伸单精确度(43位以上,很少使用)与延伸双精确度(79位以上)。
C语言的float通常是指IEEE单精确度,而double是指双精确度,而Python中只有双精确度(float)。
现在只说说双精确度(64位比特储存浮点数),下文看懂了,剩下的三种都自然而然就懂。
大家还记得科学计数法吗?不记得的问百度去,免得压不住小学数学老师的棺材板。
十进制 0.75 科学计数法 7.5*10^-1
十进制 2.75 科学计数法 2.75*10^0
类比
二进制 0.11 科学计数法 1.1*2^-1
二进制 10.11 科学计数法 1.011*2^1
可以得出一个通式
V=(-1)^S*M*2^E
S为 0 or 1
1<=M<2
E是整数
现在我们就开始分配那储存浮点数的64位比特
最高的1位比特(bit)Sign储存的是符号位S,(-1)^S表示符号(正负号,S=0正号,S=1为负);
接着的11位比特(bit)Exponent储存的是2^E幂运算的指数E,当然E的储存也要转换为二进制数进行,(E为负数小数点向前移|E|位,为正小数点向后移|E|位);
剩下的52位比特(bit)Significant储存有效数字M(这也是Python的浮点数大约精确的17位的原因,为什么,自己想去)。
E转换为二进制数储存,和浮点的储存不同
E有正负,E转换为二进制储存,不像浮点数一样,用单独1位比特(bit)来储存符号,它是借助一个中间值,来实现正负数的表达。
中间值:11位比特(bit)Exponent储存的是E,所以E的取值范围理论上是 [0,2047] 2^11-1=2047 中间值=1023(取值范围最中间的那个数)
IEEE754规定中间值1023那个位置表示E=0,小于中间值为负数(小多少就是负多少),大于中间值为正数(大多数就是正多少),之后在将经过中间值处理的数转换为二进制,存在Exponent中
例如:E=11
有效数M的储存也自己的规则(也是可以储存小数点的原因)
IEEE 754规定Significant储存的只是M中小数点后的数(存了52位小数点后的二进制数,所以应该存了52位有效数包括开头的1),
因为M的都是以1.开头的(别问我为什么,说明你二进制科学计数法,还不是很明白),所以只要在取出Significant储存的二进制数前面加上1.(IEEE 754就是用这个方法绕开储存如何小数点问题的)。
讲了这么多,但是还是没讲到痛点啊!
0.1连续的相加10次为什么不是1,而是0.999…
走过路过不要错过啊,止痛良药来了。
我们就用上述的IEEE754的标准把十进制0.1储存进计算机内存中
0011(0舍1入)
S=0 E=1111 1110 11 Significant中存的是 1 0011 0011 0011 0011 0011 0011 0011 0011 0011 0011 0011 0011 010
64位比特(bit)存: 1111 1110 11 1 0011 0011 0011 0011 0011 0011 0011 0011 0011 0011 0011 0011 010
提取内存中刚存进去的0.1的二进制表达式
Significant中存的是 1 0011 0011 0011 0011 0011 0011 0011 0011 0011 0011 0011 0011 010 前面添加 0.0001就是提取出来的二进制0.1(因为E=-4,且IEEE 754帮你存着1.)
所以从内存提取出来的0.1的二进制是 0001 1 0011 0011 0011 0011 0011 0011 0011 0011 0011 0011 0011 0011 010
下面是计算二进制小数转十进制小数的脚本
import re
a=re.sub(' ','','00011 0011 0011 0011 0011 0011 0011 0011 0011 0011 0011 0011 0011 010')
# 去空格
n=0
sum=0
for i in a :
n-=1
sum+=int(i)*2**(n)
print( "%.17f" %sum) # 格式化
# 输出结果
# 0.10000000000000001
最后提一个问题,E转换为二进制时,为什么要有中间值的方式,这样更帅?
对哦,中间值的转换为二进制刚好为11个1,1111 1111 111哦。。。。
欢迎评论,番茄,鸡蛋都砸过来吧!!!
我和Python的Py交易》》》》》》 浮点数的身世字谜的更多相关文章
- 我和Python的Py交易》》》》》》数据类型
Python里的变量 ---门牌 Python在使用变量之前无须定义它的类型,但是必须声明以及初始化该变量. Python中给变量赋值就是声明,初始化变量(也就是创建一个相应数据类型的对象,而那些数据 ...
- 我和Python的Py交易》》》》》》 命名空间的小弟作用域
命名空间的小弟作用域 在这要明确一个观点,在Python中万物皆对象,而变量指向的就是对象. 变量可以是 类名,函数名,储存数据的变量…… 对象可以是 类 ,被封装的一段代码(函数),数据…… 命名 ...
- 我和Python的Py交易》》》》》》函数
一 函数是什么? 是数学中的函数? Python中 函数是指将一组语句的集合通过一个名字(函数名)封装起来的一段代码.(所以这里的函数是subroutine子程序) 那要函数干嘛.不都是代码吗?只不 ...
- python调用py中rar的路径问题。
1.python调用py,在py中的os.getcwd()获取的不是py的路径,可以通过os.path.split(os.path.realpath(__file__))[0]来获取py的路径. 2. ...
- python gettitle.py
#!/usr/bin/env python # coding=utf-8 import threading import requests import Queue import sys import ...
- Python pydoc.py
1. 查看帮助,我们可以在python命令行交互环境下用 help函数,比如: 查看 math 模块: >>> help('math')Help on built-in module ...
- django 1.7之后python manage.py syncdb没有了
在命令行输入python manage.py createsuperuser按照提示输入即可记得先初始化表. django>1.7 python manage.py makemigrations ...
- Python安装mysql-python错误提示python setup.py egg_info
做python项目,需要用到mysql,一般用python-mysql,安装时遇到错误提示如下: Command "python setup.py egg_info" failed ...
- python __init__.py用途
转自http://www.cnpythoner.com/post/2.html Python中的Module是比较重要的概念.常见的情况是,事先写好一个.py文 件,在另一个文件中需要import时, ...
随机推荐
- OSGI介绍
OSGI介绍 OSGI简介 OSGI (Open Service Gateway Initiative)联盟成立于1999 年,它是一个非盈利的国际组织,旨在建立一个开放的服务规范,为通过网络向设备提 ...
- 在SQL Server 2008 Management Studio中修改表字段顺序
有时我们可能需要为一个已存在的数据库表添加字段,并且想让这个字段默认排的靠前一些,这时就需要为表字段重新进行排序,默认情况下在Management Studio中调整顺序并保存时会提示"不允 ...
- IDEA 的maven项目打jar 编写UDF 在hive端运行 (全过程,有录制的操作视频)
一. 前提准备 服务端hive搭建完成,可以正常创建访问表 本地端使用的IDE是Intellij IDEA(我的是2017版本,老版本需要支持创建maven项目) ,并且电脑有网. 二. ...
- java反射机制,以及对反射机制的了解,如有差池欢迎点评(初学者勿喷)
本人学习java时间不长,但是对java很感兴趣,知道有博客园这个平台果断的注册,记录我的java成长日记,这也是我的处女作,虽然很菜但是还是希望大家能见证我的成长,觉得可以的可以和我讨论一起学习 在 ...
- 终于解决文件格式问题 unix格式
关于这个问题,今天终于找到方法 file-setting下 左侧code style line separator下拉选择unix就可以了 http://www.cnblogs.com/sunfa ...
- Myeclipse+selenium2.0+Junit+TestNg环境搭建
这周末把自动化的环境搭好了,在网上也百度了很多,现在分享下,希望大家少走一点歪路. 需要用到的安装包都在这个里面,自取: 链接:https://pan.baidu.com/s/10ohf757ztgN ...
- SSH学习之路(一).Net开发与Java Web开发
摘要:一直再使用.net mvc5开发,期间学习过java web相关的知识,现如今想要进阶一下便开始学习ssh框架. 1..net web开发 对于微软的东西,开发者考虑的东西不需要太多,你新建一个 ...
- arcis api for js 值 3.17 本地部署
1. 引言 在学习 ArcGIS API 的过程中,如果我们引用在线的 API,在没有网络或者网络差的情况下,会影响到我们的学习效率,本篇文章就是为了解决这个问题.下载 ArcGIS API 之后,部 ...
- cw2vec理论及其实现
导读 本文对AAAI 2018(Association for the Advancement of Artificial Intelligence 2018)高分录用的一篇中文词向量论文(cw2ve ...
- 一个能拖动,能调整大小,能更新bind值的vue指令-vuedragx
一. 背景说明 开发一个可自定义组件化门户配置页面,期间采用了vue框架作为前端视图引擎,作为一个刚入手vue的萌新,开发第一个功能就遇到了拦路虎.需要一个拖动并且可改变大小的容器盒子.当时查看vue ...