【算法】解析IEEE 754 标准

article/2025/6/9 10:53:24

目录结构:

contents structure [-]
  1. 浮点数的存储过程
    1. 次正规数(Denormalized Number)
    2. 零(zero)
    3. 非数值(NaN)
    4. 无穷大(infinity)
  2. 除数为0.0会发生什么
  3. 浮点数的范围
  4. 浮点数的精度
  5. 参考文献

IEEE 754(Institute of Electrical and Electronics Engineers)在1985年发布,该标准是为了统一规范浮点数的存储。

 

1.浮点数的存储过程

在IEEE 754标准中浮点数由三部分组成:符号位(sign bit),有偏指数(biased exponent),小数(fraction)。浮点数分为两种,单精度浮点数(single precision)和双精度浮点数(double precision),它们两个所占的位数不同。

 

单精度浮点数(共32位):
1个符号位
8个指数位
23个小数位

 

双精度浮点数(共64位):
1个符号位
11个指数位
52个小数位

 

接下来笔者以单精度浮点数0.15625讲解浮点数的存储过程:
0.1562510转化为二进制就是0.001012,然后将该数写成科学计数法(scientific notation),根据IEEE 754的规定,小数点的左边只能有一个1,所以最终的科学计数法形式是:

0.1562510 = 0.001012 = 1.012 * 10-3

然后就可以得到小数部分为.012,指数部分为-3。

最终在内存中的存储结果就是如下图:

符号位(sign):0,因为该数是正数(1表示负数)。

有偏指数(biased exponent):-3 + 偏移量(bias),在单精度浮点数中偏移量是127,因此127+(-3)=124,所以偏移指数是124。在双精度浮点数中偏移量是1023,因此偏移指数是1020。

小数(fraction):.010000000000000000000002

 

在上面已经展示了浮点数的存储过程,接下来再仔细说一说有偏指数,还是拿单精度浮点数来说吧! 在单精度浮点数中,有8位可以用来存储指数(范围就是:0~255),那么怎么表示负的指数呢?IEEE 754标准的制定者为了解决这个问题,约定了指数偏移量(单精度的偏移量是127),指数值要在加上偏移量后才能进行存储,这样就能表示指数的正负值了。通常情况下,如果存储的值大于偏移量,那么就意味着指数是正的;如果存储的值小于偏移量,那么就意味着指数是负的;如果存储的值等于偏移量,那么就意味着指数为0。

 

下面的对应关系,显示了有偏指数代表的各种含义:

0 == 特殊情况:零(zero) 或 次正规数(subnormal)
1 == 2 ^ -126...
125 == 2 ^ -2
126 == 2 ^ -1
127 == 2 ^  0
128 == 2 ^  1
129 == 2 ^  2...
254 == 2 ^ 127
255 == 特殊情况:无穷大(infinity) 或 非数值(NaN)

 

1.1 次正规数(Denormalized Number)

IEEE 754的设计者注意到,除了0.0所有的二进制的科学计数法都有一个1在小数点的左边。在上面也提到过,在写成标准的科学计数法的形式后,小数点的左边只能有一个1。
比如:
25.010 == 110012 = 1.10012 * 24
0.62510 == 0.1012 = 1.012 * 2-1
小数点的左边都是以一个1开始的,为了节约内存,它们规定:所有数在小数点左边默认有一个1。

按照这个规定的话,那么能够表示的最小正数就是:
0 00000001 000000000000000000000012 = 1.000000000000000000000012 * 2-126

如果指数全为0,只能表示数字0的话,那么表示小数位的23位就没有利用起来。于是IEEE754的设计值,规定了一种新的数 次正规数(Subnormal Number Or Denormalize Number)。规定如下:
如果指数位全为0的话,那么在科学计数法中小数点的左边就默认为一个0。这样的数,就被称为次正规数。

在次正规数中所有的偏移指数位都是0,于是规定在单精度浮点数中指数应该为-126(并非-127),在双精度浮点数中指数应该为-1022(并非-1023)

 

所以最小的正数就应该是:
0 00000000 000000000000000000000012 = 0.000000000000000000000012 * 2-126

1.2 零(zero)

数值0被特殊表示:

符号位(sign) = 0或1
有偏指数(biased exponent) = 0
小数(fraction)= 0

0的内存二进制码为:

0 00000000 00000000000000000000002
1 00000000 00000000000000000000002

 

1.3 非数值(NaN)

有一些算数操作是非法的,比如对负数开根号。这类非法操作被称为浮点数异常(floating-point exception),异常结果由特殊字符NaN(Not a Number)表示。

符号位(sign) = 0或1
有偏指数(biased exponent)= 所有位都是1
小数(fraction) = 除了所有位都是0的数(因为所有为0,表示无穷大)

小数位只要不全为0,就表示非数值。
0 11111111 111111111111000000100002

1 11111111 111111111111000000100002

 

1.4 无穷大(infinity)

无穷大有两种,正无穷大(Positive Infinity)和负无穷大(Negative Infinity)。

符号位(sign) = 0表示正无穷大,1表示负无穷大。
有偏指数(biased exponent) = 所有位都是1
小数(fraction) = 所有位都是0.

正无穷大
0 11111111 000000000000000000000002
负无穷大
1 11111111 000000000000000000000002

 

2.除数为0.0会发生什么

如果计算机是采用的IEEE 754的标准(绝大部分计算机都是采用该标准)。那么当除数为0.0时,会发生不可预期的行为(注意程序不会中断)

#include <iostream>
#include <limits>
int main(){
//is_iec559是否支持IEC-559 / IEEE-754标准
std::cout << std::numeric_limits<float>::is_iec559 << std::endl;
std::cout << (1.0 / 0.0) << std::endl;
std::cout << (-1.0 / 0.0) << std::endl;
std::cout << (0.0 / 0.0) << std::endl;
return 0;
}

程序的输出结果是:

1
inf
-inf
-nan

 

3.浮点数的范围

在学习过上面的知识后,我们清楚了IEEE 754中浮点数在内存中的表示形式,我们也知道0(zero)是最小的(这里和下面只讨论非负数),次正规数(Denormalized Number)的表示范围比0大,正规数(normalized Number)表示的范围比次正规数大。

下面清楚的显示了一些范围和数值:


0 00000000 000000000000000000000012 = 0000 000116 = 0.12 × 2-22 × 2-126  =  2−126 × 2−23 = 2−149 ≈ 1.4012984643× 10−45 

(最小的次正规数,smallest positive subnormal number)

0 00000000 111111111111111111111112 = 007f ffff16 = 0.111111111111111111111112 * 2-126  =  2−126 × (1 − 2−23) ≈ 1.1754942107 ×10−38

(最大的次正规数,largest subnormal number)

 

0 00000001 000000000000000000000002 = 0080 000016 = 1.02 × 21-127 = 2−126 ≈ 1.1754943508 × 10−38

(最小的正正规数,smallest positive normal number)

0 11111110 111111111111111111111112 = 7f7f ffff16 = 1.111111111111111111111112  × 2254-127 =  2127 × (2− 2−23) ≈ 3.4028234664 × 1038

(最大的正正规数,largest normal number)

 

0 01111110 111111111111111111111112 = 3f7f ffff16 = 1.111111111111111111111112 × 2126-127 = 1 − 2−24 ≈ 0.9999999404

(比数值1小的最大数,largest number less than one)

0 01111111 000000000000000000000002 = 3f80 000016 = 1.02 × 2127-127  = 1.02 × 20 = 1

(数值1,one)

0 01111111 000000000000000000000012 = 3f80 000116 = 1.000000000000000000000012 × 2127-127 = 1 + 2−23 ≈ 1.0000001192

(比数值1大的最小数,smallest number larger than one)

 

1 10000000 000000000000000000000002 = c000 000016 = −2

0 00000000 000000000000000000000002 = 0000 000016 = 0

1 00000000 000000000000000000000002 = 8000 000016 = −0

 

0 11111111 000000000000000000000002 = 7f80 000016 = infinity(正无穷)

1 11111111 000000000000000000000002 = ff80 000016 = −infinity(负无穷)

 

0 10000000 100100100001111110110112 = 4049 0fdb16 ≈ 3.14159274101 ≈ π ( 圆周率,pi )

0 01111101 010101010101010101010112 = 3eaa aaab16 ≈ 0.333333343267 ≈ 1/3

 

x 11111111 100000000000000000000012 = ffc0 000116 = qNaN (on x86 and ARM processors)

x 11111111 000000000000000000000012 = ff80 000116 = sNaN (on x86 and ARM processors)

通常我们所说的浮点数的范围,都是指的正规数的存储范围。

LevelWidthRange at full precision
Single precision32bits±1.18×10−38 to ±3.4×1038
Double precision64 bits±2.23×10−308 to ±1.80×10308

 

4.浮点数的精度

在单精度浮点数中的二进制小数位有23个,所能表示2^23个数,那么只需要换算成在10进制下能够表示相同个数的位数,就可以得到精度了。
10n = 223
10n = 8388608
106 < 8388608 < 107
所以但精度浮点数的精度为6位,同理也可以得到双精度浮点数的精度为15位。

注意:精度为6位,并不是表示所有小于6的数都可以被精确存储,比如0.9。因为这个精度是由二进制的精度位数计算而来的。

所以浮点数的相等判断中,只需要判断他们的差值小于精度就可以了。

#include <stdio.h>      /* printf */
#include <math.h>       /* fabs */int main ()
{float f1 = 0.007;float f2 = 0.009;int res = ( fabs(f1-f2) < 1e-6 );printf ("f1 == f2 is : %s\n",res?"true":"false");return 0;
}

输出结果:

f1 == f2 is : false

 

5.参考文献

Single-precision floating-point format_Wikipedia
IEEE 754-1985_Wikipedia
What is a subnormal floating point number?
What is a “bias value” of floating-point numbers?

转载于:https://www.cnblogs.com/HDK2016/p/10506083.html


http://chatgpt.dhexx.cn/article/FjnECb7A.shtml

相关文章

如何深刻理解IEEE浮点数的表示(IEEE floating-point representation)

引言 大家都知道&#xff0c;可以在计算机处理器直接运行的是由0,1构成的机器代码(machine code)&#xff0c;本文将介绍浮点数(floating-point number )在机器码中是如何被编码表示的。 整数(integer)是如何被编码的呢&#xff1f;小伙伴们应该听过补码&#xff0c;原码&…

【论文学习】7、ieee802.11ah中基于深度学习的载波频偏估计

摘要 基于ieee802.11标准的Wi-Fi系统是最流行的无线接口&#xff0c;它采用先听后讲&#xff08;LBT&#xff09;的方式进行信道接入。大多数基于LBT的系统的显著特征是&#xff0c;发射机使用在数据之前的前导码来允许接收机执行分组检测和载波频率偏移&#xff08;CFO&#…

计算机中的小数 IEEE754

计算机中的小数 IEEE754 进制计数系统 在基数b的位置记数系统(其中b是一个正自然数&#xff0c;叫做基数)&#xff0c;b个基本符号(或者叫数字)对应于包括0的最小b个自然数。 要产生其他的数&#xff0c;符号在数中的位置要被用到。最后一位的符号用它本身的值&#xff0c;向…

计算机组成原理:IEEE754标准中,为什么指数真值e变成阶码加上的偏移值是127不是128?

1.浮点数在计算机里的存储方式 以32位为例,短浮点型float,按照按照 IEEE754 标准,在计算机里的存储格式如下 数符S&#xff1a;表示浮点数的符号&#xff0c;占1位&#xff0c;0—正数、1—负数&#xff1b; 尾数M&#xff1a;23位&#xff0c;原码纯小数表示&#xff0c;小数…

ieee sci 期刊 写作经验 分享 博士发展阶段

0. 前言 本文仅记录最近我在论文写作中遇到的问题&#xff08;感谢老师、师兄的用心指导&#xff09;&#xff0c;仅仅是我的个人分享&#xff0c;不适用于所有人。 1. introduction - 如何切入自己的工作&#xff1f; 1.1 不要没事找事 例子&#xff1a; 比如你做的是目标…

谈谈论文的发表(电光与控制,IEEE ACCESS)

前言 目前&#xff0c;科研任务差不多告一段落&#xff0c;总结一下发表论文的经验以及经历。 2021年3月&#xff0c;录用IEEE ACCESS一篇&#xff0c;本来老师想让投IEEE trans系列&#xff0c;但是工作的深度差一点&#xff0c;并且没有很好的实例论证&#xff0c;只有仿真&…

IEEE 754标准

普通规则下: 移码: 补码的基础上将符号位取反。注意:移码只能用于表示整数 移码的定义: 移码 真值 偏置值(确定移码&#xff0c;首先要确定偏置值) 偏置值一般取2^n-1&#xff0c;此时移码 补码符号位取反 IEEE 754规则下&#xff1a; 偏置值 2^n-1 - 1 相当于将普通规…

IEEE 754浮点数工业标准

文章目录 浮点数概述浮点数的格式IEEE 754标准规定的浮点数的格式IEEE 754偏移量与指数范围问题IEEE 754中浮点数值的三种情况&#xff1a;1. 规格化的浮点数的值2. 非规格化的值3. 特殊值 Java中的浮点数类型 浮点数概述 浮点数&#xff0c;是属于有理数中某特定子集的数的数字…

SPSS Modeler导入excel文件时出现“无法读取文件列名”解决方法

SPSS Modeler导入excel文件时出现“无法读取文件列名”解决方法 经过本人多次尝试&#xff0c;终于发现了原因 原因是&#xff1a;excel文件在后台打开了&#xff0c;因此spss modeler读取不了 解决方法&#xff1a;关闭正在打开的该excel文件&#xff0c;再读取即可 如果解决了…

SPSS Modeler 数据导入操作

1、导入文本文件 数据选项卡&#xff0c;主要是指定所读取数据的基本类型&#xff0c;通常无需修改&#xff0c;若需修改要先在覆盖那里打钩&#xff0c;然后下拉存储框进行修改 过滤选项卡是选择读取数据时读取哪些数据&#xff0c;同时可以修改变量名。 类型选项卡是指定读取…

SPSS导入excel文件时,保留4位小数点

SPSS导入excel文件时&#xff0c;保留4位小数点 SPSS导入excel文件时&#xff0c;会只保留整数部分&#xff0c;而小数点部分的数据不显示&#xff0c;如下图&#xff1a; 我尝试在SPSS的变量视图里将小数点位数改成4位&#xff0c;如图&#xff0c;但是导入数据后&#xff0c…

SPSS for Mac导入Excel表格找不到文件、以及“文件受密码保护”报错问题的解决办法

SPSS版本25&#xff0c;在导入Excel文件时显示不出来&#xff0c;需要移动到磁盘-用户-apple里面&#xff0c;我这里是我自己的用户名&#xff0c;移进去就可以看到了 之后可以用导入文件打开&#xff0c;也可以直接拖到数据视图&#xff0c;但是我这边又出现了一个小问题 出现…

SPSS数据抽取

SPSS数据抽取 数据抽取一般分为两类&#xff1a;字段拆分和随机抽样 字段拆分 数据抽取&#xff0c;也称为数据拆分&#xff0c;是只保留原数据表中的某些字段、记录的部分信息&#xff0c;形成一个新字段、新记录。 在spss中导入我们需要的数据&#xff0c;变量主要包含如…

利用SPSS做数据分析②之数据处理1

SPSS数据处理有六个步骤&#xff0c;分别是&#xff1a; 数据导入数据清洗数据抽取数据合并数据分组数据标准化 数据处理是根据数据分析的目的&#xff0c;将收集到的数据&#xff0c;用适当的处理方法进行加工、整理&#xff0c;形成适合数据分析的要求样式&#xff0c;它是数…

SPSS怎么筛选无效数据

我们在用IBM SPSS进行数据分析的时候&#xff0c;经常会遇见这样一种情形&#xff0c;想把不符合自己分析要求的数据全部筛掉。我们把这些要筛掉的数据叫作无效数据&#xff0c;无效数据不筛选掉不但会降低分析的效率&#xff0c;而且会影响最终结果的准确性。 要想提高准确性…

SPSS学习笔记

什么都写 插入个案&#xff1a;指一行 插入变量&#xff1a;指一列 设置 语言 编辑->选项 语言中可以选择输出的语言和界面的语言 变量定义 左下角切换到变量视图&#xff0c;可以修改变量的属性 1.类型可选&#xff0c;注意会影响到后面测量中的选项&#xff0c;如…

SPSS数据插补方法

问题&#xff1a;ArcGIS多值提取至点的数据有很多缺失值 这是对多个区域分区统计后的结果&#xff0c;由于ET的质量不高&#xff0c;所以有很多缺失值 那么&#xff0c;怎样才能将这些值进行插补成我们认为可靠的格式呢&#xff1f; 第一步-将arcgis多值提取至点的数据整理成…

python数据导入spss_spss-数据抽取-拆分与合并

数据抽取也成为数据拆分&#xff0c;是指保留、抽取原数据表中某些字段、记录的部分信息&#xff0c;形成一个新字段、新纪录。分为&#xff1a;字段拆分和随机抽样两种方法。 一&#xff1a;字段拆分 如何提取“身份证号码”字段。身份证号码里面包含了许多信息&#xff0c;…

SPSS数据清洗

SPSS数据清洗 关于spss对数据的清洗&#xff0c;就是将多余重复的数据筛选清楚&#xff0c;将确实的数据补充完整&#xff0c;将错误的数据纠正活删除。 下面主要内容是关于最常用的重复数据操作&#xff1a; 首先在spss中导入需要去重的数据&#xff1a; 选择数据菜单&…

SPSS读取数据文件

1.读取Excel数据文件 &#xff08;1&#xff09;选择“文件”-“打开”-“数据”,在弹出的“打开数据”对话框下选择Excel文件&#xff0c;如图所示 &#xff08;2&#xff09;选择要打开的Excel文件&#xff0c;点击“打开”&#xff0c;如图所示 &#xff08;3&#xff09;可…