文档章节

有趣的二进制-浮点数

wier
 wier
发布于 2017/05/22 07:55
字数 2174
阅读 179
收藏 3
点赞 0
评论 0

本篇是二进制系列第三篇,如若你有兴趣,请持续关注,后期会持续更新。其他文章列表如下:

有趣的二进制

有趣的二进制—高效位运算

一、 精度

如果你有看过《有趣的二进制》这篇文章,你就会明白进制(不局限于二进制)中的小数是如何表示。因为每种进制都有其局限性,也就是约数的问题,比如

同样是1/3,在三进制下正好分干净,但在十进制下就总也分不完。十进制只能近似的表示1/3而无法精确的表示1/3。

同样是0.1,在十进制下可以精确的表示为0.1,而在二进制下只能近似的表示0.00011001100110011...(循环0011)

计算机中,存储数据的方式是采用二进制,因此在有限的存储空间下,绝大部分的十进制小数都不能用二进制浮点数来精确表示。一般情况下,你输入的十进制浮点数仅由实际存储在计算机中的近似的二进制浮点数表示。不要相信浮点数结果精确到了最后一位,也永远不要比较两个浮点数是否相等。

需要说明的是,虽然目前计算机表示的精度多数都是近似值,但多数情况下都够用了,如果你对精度有更高要求,每一种语言都有自己实现和处理方式。特别要注意的是防止上溢和下溢现象的发生。

 

二 、 IEEE 754 标准

IEEE 754

IEEE二进制浮点数算术标准IEEE 754)是20世纪80年代以来最广泛使用的浮点数运算标准,为许多CPU与浮点运算器所采用。主要规范如下:

这个公式中:

1、s(Sign):符号,表示是正数还是负数。0正数,1负数

2、E(Exponent):指数域,E是2的指数,类似于科学计数法中(a×10^n)中的n,如此E是负数就可以表示小数了。不过这里E是一个无符号整数,32位的时候,E的占用8位,取值范围0-255,存储E的时候我们称为e,它是E的值与一个固定值(32位的情况是127)的和(e=E+bias,E=e-bias,bias=127)。采用这种方式表示是因为,指数的值可能为正也可能为负,如果采用补码表示的话,符号位S和Exp自身的符号位将导致不能简单的进行大小比较。

3、M(Mantissa):尾数域,浮点数具体的数值. 1≤M<2,隐含的以1开头表示,M表示的二进制表达式为1.xxx...,第一位总是1,因此IEEE 754规定,保存M时,默认这个数的第一位总是1,因此可以被舍去,只保存后面的xxxxxx部分。

示例

比如十进制的3.25,我们分为以下几步进行转换。

1、转换二进制

3.25 这整数部分3转换为二进制是11,小数部分0.25 转换为二进制为2^-2,也可以按照乘以 2 取整数位的方法:

(1) 0.25 x 2 = 0.5  取整数位 0 得 0.0
(2) 0.5 x 2 = 1  取整数位 1 得 0.01

如此3.25转化为二进制为11.01

2、有效数(Mantissa)

上述规则我们知道,尾数部分最高有效位(即整数字)是1,也就是尾数有一位隐含的二进制有效数字。因此我们转换尾数的时候,始终保持最高位为1(小数点左边),通过二进制科学计数法转换,我们得到11.01=1.101*2^1。

3、IEEE 754 规约形式

通过上述2步,得到1.101*2^1。我们采用规约形式获取填充3个部分

s(Sign):正数=0;

E(Exponent):E=1,e=E+bias=1+127=128。此处存储的e,是经过以127作为偏移量调整的。

M(Mantissa):1.101 中,我只获取有效数(舍去整数部分1,只取小数部分)101

因此存在计算机中的3.25 浮点数是:

特殊值

从wiki上可以看到依据指数是否为0 ,还可以分为一下几种情况

指数不全为0或者不全为1此时为规约形式,如上述的示例。尾数部分,默认整数部分是1,不存储,获取后第一位默认为1。指数部分有偏移量

E全为0  。此时为非规约形式。为何要引入非规则浮点数,当小于的数会下溢为0,对于高精度来说这是不能接受的,而引入不规则浮点数后,小于的数才会下溢为0 。

E全为1 。尾数为0,则表示无穷大。非零则表示NaN(浮点数排序这种特殊问题需要处理)

运算方式

一般浮点数的运算流程如下,非规则浮点计算加法时“对阶”计算有不同,不再细说。

  1. 指数项对齐。指数项对齐,小的向大的对齐,如果判断大小,则上述指数中的偏移量就起很大作用了,指数大的必然大,后续可以减少判断
  2. 尾数求和。对齐后,对尾数进行加减处理
  3. 规则化。对尾数进行截取,保证精度
  4. 舍入。判断丢失的数值,进行舍入
  5. 判断结果。判断结果是否溢出

三、非规范化浮点数

 

为何要引入非规范化浮点数

引入一个精度失准的事故:

On 25 February 1991, a loss of significance in a MIM-104 Patriot missile battery prevented it intercepting an incoming Scud missile in Dhahran, Saudi Arabia, contributing to the death of 28 soldiers from the U.S. Army’s 14th Quartermaster Detachment.[25] See also: Failure at Dhahran

1991年2月25日,在MIM-104爱国者导弹电池中,一个重要的精准丢失阻止了它在沙特阿拉伯达哈兰拦截一架新的飞毛腿导弹,造成美军第十四军区分离队28名士兵死亡。

对于规则浮点数而言,指数项范围为01-FE(1到254),当小于的浮点数,用规格化数值表示,运算的时候会被电脑当作0来处理,如果精度能够再次提高一些的话,就不会出现这种情况了,因此引入不规则浮点数后,小于的数才会下溢为0 。

采用非规约浮点数,用来解决填补绝对值意义下最小规格数与零的距离,如上图所示,仅仅用规则浮点数的表示方式,0到最小正常数之间的间隔要远远大于最小正常数到次小正常数之间的间隔(2^-126 * 2^-23 = 2^-149),可以说是非常突然的下溢出到0,这是不满足我们的期望的。因此选择约定小数点前一位可以为0,剩下的一小段区间(即黄色括号)再均匀划分为段,如此就多了2^23精度,可以精确到附近。

 

引入非规范化浮点数带来的问题

《你应该知道的浮点数基础知识》引入一个算法题,很好了诠释导致计算速率方面的问题。我简单贴一下:

 const float x=1.1;
 const float z=1.123;
 float y=x;
// 算法1  
 for(int j=0;j<90000000;j++)
    {
        y*=x;
        y/=z;
        y+=0.1f;
        y-=0.1f;
    }

// 算法2
for(int j=0;j<90000000;j++)
    {
        y*=x;
        y/=z;
        y+=0;
        y-=0;
    }

算法2中在进行上百次循环以后,y被标识为非规格化浮点,最终导致的结果是算法2比算法1慢了整整7倍左右。

 这就是非规则浮点数的计算速度慢于规则浮点数,虽然下溢下沉了,但需要CPU额外进行解码和编码标识,如此,效率缓慢,极端情况下,规格化浮点数操作可能比硬件支持的非规格化浮点数操作快100倍。

另外非规则浮点数无法解决计算过程中下溢的产生,因为只是精度精确到附近,当有更小的浮点数时候,依然会下溢为0。

 

 

© 著作权归作者所有

共有 人打赏支持
wier
粉丝 658
博文 46
码字总数 122193
作品 0
东城
高级程序员
Python 的浮点数损失精度问题(为什么说双精度浮点数有15位十进制精度)

本篇讨论的现象可以从下面这段脚本体现出来: >>> x = 0.0>>> for i in range(10): 0.10.20.300000000000000040.40.50.60.70.79999999999999990.89999999999999990.9999999999999999>>> 即:......

lionets ⋅ 2013/12/21 ⋅ 0

浮点型数据在内存中存储的表示

实数在内存中以规范化的浮点数存放,包括数符、阶码、尾数。数的精度取决于尾数的尾数。比如32位机上float型为23位(因为规范化数的数码最高位恒为1,不必存储,实际精度为24位,下面会有详解...

Crazy_C ⋅ 2012/10/12 ⋅ 0

浮点数的基础知识

1.浮点数的十进制表现形式 ·我们知道,在 十进制中通常一个浮点数可以用科学计数法来表示,举例: eg.1 -306.5可以表示为-0.3065*10^3 其中 - 是符号,指数3是阶或称阶码,0.3065是小数部分...

follitude ⋅ 2016/05/12 ⋅ 0

Java中浮点型数据Float和Double进行精确计算的问题

一、浮点计算中发生精度丢失 大概很多有编程经验的朋友都对这个问题不陌生了:无论你使用的是什么编程语言,在使用浮点型数据进行精确计算时,你都有可能遇到计算结果出错的情况。来看下面的...

Junn ⋅ 2013/06/10 ⋅ 1

浮点数的表示和运算

1 浮点数的表示 通常,我们可以用下面的格式来表示浮点数 S P M 其中S是符号位,P是阶码,M是尾数 对于IBM-PC而言,单精度浮点数是32位(即4字节)的,双精度浮点数是64位(即8字节)的。两者...

guoliang ⋅ 2015/08/10 ⋅ 0

浮点数加法引发的问题:浮点数的二进制表示

1、问题: 之前有同学问过这样一个问题: echo|awk '{print 3.99 -1.19 -2.80}'4.44089e-16 类似的问题还有在 java 或者 javascript 中: 23.53 + 5.88 + 17.64 = 47.05 23.53 + 17.64 + 5.8...

xrzs ⋅ 2013/08/26 ⋅ 0

据说有99%的人都会做错的面试题

这道题主要考察了面试者对浮点数存储格式的理解。另外,请不要讨论该题本身是否有意义之类的话题。本题只为了测试面试者相关的知识是否掌握,题目本身并没有实际的意义。 下面有6个浮点类型变...

androidguy ⋅ 2014/08/25 ⋅ 0

32位16进制浮点数转化成10进制数

{ } 浮点数保存的字节格式如下: 地址 +0 +1 +2 +3 内容 SEEE EEEE EMMM MMMM MMMM MMMM MMMM MMMM 这里 S 代表符号位,1是负,0是正 E 偏移127的幂,二进制阶码=(EEEEEEEE)-127。 M 24位的尾...

_编程菜鸟_ ⋅ 2015/08/14 ⋅ 0

代码之谜(五)- 浮点数(谁偷了你的精度?)

光棍节加长版 如果我告诉你,中关村配置最高的电子计算机的计算精度还不如一个便利店卖的手持计算器,你一定会反驳我:「今天写博客之前又忘记吃药了吧」。 你可以用最主流的编程语言计算 ,...

justjavac ⋅ 2012/11/13 ⋅ 5

浮点数的二进制表示

1. 前几天,我在读一本C语言教材,有一道例题:   #include   void main(void){     int num=9; / num是整型变量,设为9 /     float pFloat=# / pFloat表示num的内存地址,但是...

阮一峰 ⋅ 2010/06/06 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

Sqoop

1.Sqoop: 《=》 SQL to Hadoop 背景 1)场景:数据在RDBMS中,我们如何使用Hive或者Hadoop来进行数据分析呢? 1) RDBMS ==> Hadoop(广义) 2) Hadoop ==> RDBMS 2)原来可以通过MapReduce I...

GordonNemo ⋅ 18分钟前 ⋅ 0

全量构建和增量构建的区别

1.全量构建每次更新时都需要更新整个数据集,增量构建只对需要更新的时间范围进行更新,所以计算量会较小。 2.全量构建查询时不需要合并不同Segment,增量构建查询时需要合并不同Segment的结...

无精疯 ⋅ 29分钟前 ⋅ 0

如何将S/4HANA系统存储的图片文件用Java程序保存到本地

我在S/4HANA的事务码MM02里为Material维护图片文件作为附件: 通过如下简单的ABAP代码即可将图片文件的二进制内容读取出来: REPORT zgos_api.DATA ls_appl_object TYPE gos_s_obj.DA...

JerryWang_SAP ⋅ 47分钟前 ⋅ 0

云计算的选择悖论如何对待?

导读 人们都希望在工作和生活中有所选择。但心理学家的调查研究表明,在多种选项中进行选择并不一定会使人们更快乐,甚至不会产生更好的决策。心理学家Barry Schwartz称之为“选择悖论”。云...

问题终结者 ⋅ 54分钟前 ⋅ 0

637. Average of Levels in Binary Tree - LeetCode

Question 637. Average of Levels in Binary Tree Solution 思路:定义一个map,层数作为key,value保存每层的元素个数和所有元素的和,遍历这个树,把map里面填值,遍历结束后,再遍历这个map,把每...

yysue ⋅ 今天 ⋅ 0

IDEA配置和使用

版本控制 svn IDEA版本控制工具不能使用 VCS-->Enable Version Control Integration File-->Settings-->Plugins 搜索Subversion,勾选SVN和Git插件 删除.idea文件夹重新生成项目 安装SVN客户......

bithup ⋅ 今天 ⋅ 0

PE格式第三讲扩展,VA,RVA,FA的概念

作者:IBinary 出处:http://www.cnblogs.com/iBinary/ 版权所有,欢迎保留原文链接进行转载:) 一丶VA概念 VA (virtual Address) 虚拟地址的意思 ,比如随便打开一个PE,找下它的虚拟地址 这边...

simpower ⋅ 今天 ⋅ 0

180623-SpringBoot之logback配置文件

SpringBoot配置logback 项目的日志配置属于比较常见的case了,之前接触和使用的都是Spring结合xml的方式,引入几个依赖,然后写个 logback.xml 配置文件即可,那么在SpringBoot中可以怎么做?...

小灰灰Blog ⋅ 今天 ⋅ 0

冒泡排序

原理:比较两个相邻的元素,将值大的元素交换至右端。 思路:依次比较相邻的两个数,将小数放在前面,大数放在后面。即在第一趟:首先比较第1个和第2个数,将小数放前,大数放后。然后比较第...

人觉非常君 ⋅ 今天 ⋅ 0

Vagrant setup

安装软件 brew cask install virtualboxbrew cask install vagrant 创建project mkdir -p mst/vmcd mst/vmvagrant init hashicorp/precise64vagrant up hashicorp/precise64是一个box......

遥借东风 ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部