二进制数的科学计数法

C++中使用的浮点数包括采用的是IEEE标准下的浮点数表示方法。我们知道在数学中可以将任何十进制的数写成以10为底的科学计数法的形式,如下

其中显而易见,因为如果a比10大或者比1小都能够再次写成10的指数的形式,如

然而要想在二进制的世界中将数字写成以10为底的科学计数法的形式,着实有点麻烦,因为你首先需要将二进制的数先化成10进制的表示方法,然后才能写成科学计数法的形式。但是如果我们稍微变通一下科学计数法的标记方法,问题就变得特别的简单了。之所以数学上使用的科学计数法选用10为底,是因为我们通常使用的计数方式是十进制的。在计算机的世界中我们使用的数却是二进制的,所以我们在这个世界中应该改用以2为底的科学计数法而不是10为底的科学计数法。此时我们使用的科学计数法就表示成了如下形式,

对于一个二进制的数来说是不言而喻的,以为例

IEEE 754标准下的存储策略

IEEE标准下的浮点数存储包括三个基本的组成:符号位、指数、尾数(the sign, the exponent, the mantissa),尾数是由小数部分和一个隐含的前导数位组成。至于前导数位隐含的原因很简单(下面将会解释)。

下面的表格展示了计算机存储单精度和双精度浮点数的层次结构,包括每一部分的比特位(比特范围用方括号括出,00表示最低位)

Floating Point Components
  Sign Exponent Fraction
Single Precision 1 [31] 8 [30-23] 23 [22-00]
Double Precision 1 [63] 11 [62-52] 52 [51-00]
  • 符号位

符号位非常简单,位于存储浮点数的最高比特位,且只占1比特。0表示正数,1表示负数。通过改变该比特位的值可以改变该浮点数的符号。

  • 指数位

因为指数位既需要能够表示正指数也需要能够表示负指数,为了能够做到这一点,需要将真实的指数数值加上一个偏移值获得用来存储的指数值。对于IEEE标准下的单精度浮点数,这个偏移值是127。因此当真实的指数为0的时候,我们存储的指数位为127。如果存储的指数值是200,那么真实的指数值就应该是(200-127),即73。后面的原因会指出,指数为-127(指数位全为0)和+128(指数位全为1)会被用来存储特殊的数值。

对于双精度的浮点数,指数位的长度位11比特,偏移量位1023。

  • 尾数

尾数也被称为有效数位(significand),决定浮点数的精确度。它由隐含的前导数位(小数点左边的部分)和小数部分(小数点右边的部分)组成,因为我们采用以2为底的科学计数法表示二进制数,那么小数点左边的尾数部分自然是固定值1(),所以前导数位我们不需要明确的表示出来,我们只需要存储尾数的小数部分就可以了。

浮点数存储示例

下面就以单精度浮点数来浮点数的存储策略。

十进制数0.1562510 写成二进制的形式为0.001012。通过乘以以2为底的指数,将小数点向右移动3位后得到

这个时候我们就能够确定它的尾数的小数部分和指数分别是多少了,尾数的小数部分位.012,指数为-3。具体存储方法见下图,

在IEEE 745标准下,我们用三部分来表示一个浮点数:

  • sign = 0, 因为该浮点数为正数(用1表示负数);
  • 真实的指数是-3,但是我们用来存储的指数要在真实的指数上加上偏移量。在单精度浮点数中,这个偏移量是127,在双精度浮点数中这个偏移量是1023;所以我们这里用来存储的指数应该为(-3+127),即124。

浮点数的范围

我们先来考虑单精度浮点数的范围问题。注意到我们用来存储双精度浮点数的是一块长为32bits的内存,我们重新解释了一下该快内存中数字的存储规则使得表示数的范围大大增加。但是我们看看这样子带来了什么问题?

对于32bits的无符号整数来说,它可以表示0~232-1范围内的任意整数。但是单精度的浮点数却做不到这一点,因为浮点数的存储策略中用来存储尾数的长度只有24bits,这个时候单精度浮点数就会把将底位的部分截断,例如

     // 32-bit integer
= +1.1110000 x 2^31 // Single-Precision Float
= // Corresponding Value

这样的方法可以近似32bits的值,但是并不能得到准确的结果。忽略精确度的问题,浮点数能够表示的范围是2127,而32bits整数的表示范围是232

特殊值

按照上面的浮点数表示方法,我们发现并不能表示出数值0的大小。因为我们认为前导数位的值永远为0,这个时候无论尾数的小数部分和指数部分怎么取,浮点数的值都不会是0。为此我们规定,当指数位全部为0且尾数的小数位全为0时,这个时候浮点数的值为0。注意,+0和-0时两个不同的浮点数,即使他们的数值一样,但是浮点数的表示方式不一样。

  • 非标准化的值

当指数部分全为0,但时小数位不全为0的时候,这个时候浮点数表示的值就是非标准化的值。这个时候我们认为该浮点数的前导数位为0,因此这个时候的单精度浮点数大小为(−1)s × 0.f × 2−126,双精度浮点数的大小为(−1)s × 0.f × 2−1022,其中s为符号位上的数值,2为底的指数分别是-126和-1022,而不是-127和-1023。具体原因很简单,因为标准化所能表示的最小值是(−1)s × 1 × 2−126和(−1)s × 1× 2−1022。提出非标准化的目的就是为了表示更小的值从而提高精确度。

  • 无穷大

当指数位全为1,而尾数的小数部分全为0时表示+∞和−∞,同时通过符号位来区分+∞和−∞。所以采用IEEE 754标准表示浮点数可以很好的处理无穷大的情况。

  • 非数字(NaN)

NaN(Not a Number)用来表示非数字的值,当指数位全为1且尾数的小数部分不为0时表示NaN值。一共有两类NaN值,静态非数(QNaN, Quiet NaN)和警告非数(SNaN, Signalling NaN)。

在一个NaN的值中,如果尾数小数部分首位被置位则表示QNaN。QNaN是很重要的一类非数,四则运算经常传递QNaN值,该值通常表示不被数学上定义的运算结果,比如除数为零的时候。

在一个NaN的值中,如果尾数小数部分首位被置0则表示SNaN。它别用来表示操作中的一个异常,可以用来表示一个未被初始化变量的过早使用。

Reference:

[1] http://steve.hollasch.net/cgindex/coding/ieeefloat.html

[2] https://en.wikipedia.org/wiki/IEEE_754-1985

IEEE 754浮点数表示标准的更多相关文章

  1. IEEE二进制浮点数算术标准(IEEE 754)

    整理自IEEE 754 IEEE二进制浮点数算术标准(IEEE 754)是20世纪80年代以来最广泛使用的浮点数运算标准,为许多CPU与浮点运算器所采用.这个标准定义了表示浮点数的格式(包括负零-0) ...

  2. IEEE 754 浮点数在计算机中的表示方法

    IEEE二进制浮点数算术标准(IEEE 754)是20世纪80年代以来最广泛使用的浮点数运算标准,为许多CPU与浮点运算器所采用.这个标准定义了表示浮点数的格式(包括负零-0)与反常值(denorma ...

  3. IEEE 754 浮点数加减运算

    电子科技大学 - 计算机组成原理 小数的十进制和二进制转换 移码 定义:[X]移 = X + 2n ( -2n ≤ X < 2n ) X为真值,n为整数的位数 数值位和X的补码相同,符号位与补码 ...

  4. IEEE 754 浮点数的四种舍入方式

    四种舍入方向: 向最接近的可表示的值:当有两个最接近的可表示的值时首选"偶数"值:向负无穷大(向下):向正无穷大(向上)以及向0(截断). 说明:默认模式是最近舍入(Round t ...

  5. IEEE 754 浮点数机器表示标准

    32位字长浮点数: 共32位 1 8 23 符号位 解码 尾数 0 +    1 - 移127码 原码,隐含小数点前的首位1 不同数据类型之间转换时,隐藏着一些不容易被察觉的错误,比如int 和 un ...

  6. IEEE二进制浮点数算术标准学习

    看到有网上有个项目是要求将浮点数用二进制表示出来,需要用IEEE754标准,查了查维基和深入理解计算机系统,重新学习了一遍浮点数在计算机中的表示和内存中的存储, 先简单的做个笔记,后面需要更深入的理解 ...

  7. IEEE 754二进制浮点数算术标准

    可能很多人都遇到过浮点数精度丢失的问题,下面以JavaScript为例. 1 - 0.9 = 0.09999999999999998 纳尼,不应该是0.1么,怎么变成0.099999999999999 ...

  8. 基于 IEEE 754 标准的 单精度浮点数计算方式 (未完成)

    def dec2bin(dec): if dec < 0: s = ' dec = dec * (-1) else: s = ' e = 127 dec = float(dec) r = int ...

  9. IEEE 754标准--维基百科

    IEEE二进制浮点数算术标准(IEEE 754) 是20世纪80年代以来最广泛使用的浮点数运算标准,为许多CPU与浮点运算器所采用.这个标准定义了表示浮点数的格式(包括负零-0)与反常值(denorm ...

随机推荐

  1. 用Solidity在Truffle上构建一个HelloWorld智能合约

    原文地址:石匠的blog Truffle的环境安装在前文已经整理,这次用Solidity在Truffle写一个HelloWorld以太坊智能合约,并在testrpc上进行测试.当前的软件版本信息如下: ...

  2. 定时任务crone表达式demo

    1. cron表达式格式: {秒数} {分钟} {小时} {日期} {月份} {星期} {年份(可为空)} 2. cron表达式各占位符解释: {秒数} ==> 允许值范围: 0~59 ,不允许 ...

  3. Final发布:文案+美工展示博客

    此作业要求参见:https://edu.cnblogs.com/campus/nenu/2018fall/homework/2476 小组介绍 组长:付佳 组员:张俊余 李文涛 孙赛佳 田良 于洋 段 ...

  4. No.1_NABCD模型分析

        Reminder 之 NABCD模型分析           定位 多平台的闹钟提醒软件. 在安卓市场发布软件,发布后一周的用户量为1000.           N (Need 需求) 这个 ...

  5. 实验三 敏捷开发与XP实践 实验报告 20135232王玥

    一.实验内容 1. XP基础 2. XP核心实践 3. 相关工具 二.实验要求 1.没有Linux基础的同学建议先学习<Linux基础入门(新版)><Vim编辑器> 课程 2. ...

  6. Chapter 2 软件过程

    软件发展前期,人们只重视结果而忽略了过程,随着技术的成熟,软件过程的重要性被日益发觉.软件过程是软件工程人员为了获得软件产品而在软件工具的支持下实施的一系列软件工程活动. 软件过程的基本活动包括问题提 ...

  7. 【CS231N】5、神经网络静态部分:数据预处理等

    一.疑问 二.知识点 1. 白化 ​ 白化操作的输入是特征基准上的数据,然后对每个维度除以其特征值来对数值范围进行归一化.该变换的几何解释是:如果数据服从多变量的高斯分布,那么经过白化后,数据的分布将 ...

  8. 【大数据应用技术】作业八|爬虫综合大作业Molly134

    本次作业的要求来自:https://edu.cnblogs.com/campus/gzcc/GZCC-16SE2/homework/3075 前言:本次作业是爬取CBO中国票房2010-2019年每年 ...

  9. week2:个人博客作业

    1.这周写程序感想: 昨天差不多,也是这个时候看些的程序,写了4个小时程序,感触颇多.昨日,原打算,就完成程序就吧这个随笔写完结果,由于各种原因,没写一直拖到现在.就做昨天写的程序,本身题目很简单,主 ...

  10. SCRUM:第一、二天任务实现情况

    在团队项目“广商百货”的SCRUM项目中我认领的任务: LOGO设计 5.18熬夜完成LOGO设计(投票通过): 设计理念: 1.全矢量图设计,适应各种超大尺寸使用: 2.3D化透视设计,简约视效,也 ...