浮点数原理探究

简介:

一、文章来由

今天听到实验室有人问道浮点数的实现机制,之前刚好研究过原码、反码、补码、移码的关系,而这类问题很底层,一般容易忽视。干脆打破沙锅问到底,彻底搞清楚这个问题并留下证据,于是就有了这篇博文。

二、原码、反码、补码、移码

不要背复杂的公式,简记如下,都是用的最简单易懂的语言:
特别注意:首先要说明的是,正数的原、反、补码都一样;0的原码跟反码都有两个,因为这里0被分为+0和-0。

原码:

即直接的二进制表示,最高位为符号位:正数为0,负数为1 例如: X=+101011 , [X]原= 00101011
X=-101011 , [X]原= 10101011 位数不够的用0补全。

反码:

正数的反码与其原码相同;负数的反码是对其原码逐位取反,但符号位除外。 例如:X=-101011 , [X]原= 10101011,[X]反=11010100

补码:

正数的补码与其原码相同;负数的补码是在其反码的末位加1。
例如:X=-101011 , [X]原= 10101011,[X]反=11010100,[X]补=11010101
注:补码还有一种速算法,符号位不变,从原码低位开始从右向左数,直到遇到第一个1,保留这个1,以后的按位取反

PS:0的补码是唯一的,如果机器字长为8那么 [0]补=00000000

移码【最简单】:

不论正负数,只要将其补码的符号位取反即可。

例如:X=-101011 , [X]原= 10101011 ,[X]反=11010100,[X]补=11010101,[X]移=01010101

三、从定点到浮点

首先定点到浮点是一个飞跃,这里面的内容其实可以很简单也可以很复杂。我们一般说的整数都是定点整数,即小数点固定最后一位。但是整数既可以是整数,也可以是浮点数,例如255 是整数,而255.0 则是浮点数。

什么是浮点数?这需要从小数的表示讲起:

3.1 浮点数的表示

计算机中一个任意进制数 N 可以写成
小数表示法
m :尾数,是一个纯小数。
e :浮点的指数, 是一个整数。
R :基数,对于二进计数值的机器是一个常数,一般规定R 为2,8或16

尾数主要是决定有效位,阶码主要表示位数(小数点位置)。
阶码:用定点整数形式表示,指明小数点在数据中的位置,决定了浮点数的表示范围,常用补码或者移码表示
尾数: 决定了浮点数的数值精度,是定点小数,用补码表示,也决定了整个浮点数的符号

机器字长一定时,阶码越长,表示范围越大,精度越低
浮点数表示范围比定点数大,精度高

画一个简单易懂的表格:
c语言float型数表示

符号位(S) 阶码(E) 尾数(M)
1 8 23

浮点数表示范围如下图:

浮点数表示范围

例:
8位定点小数可表示的范围
0.0000001 — 0.1111111
1/128 — 127/128

设阶码2位,尾数4位
可表示2-11*0.0001 — 211*0.1111
0.0000001 — 111.1

设阶码3位,尾数3位
可表示2-111*0.001 — 2111*0.111
0.0000000001 — 1110000

注:float和double的范围是由指数的位数来决定的。
float的指数位有8位,而double的指数位有11位,分布如下:
float:
1bit(符号位) 8bits(指数位) 23bits(尾数位)
double:
1bit(符号位) 11bits(指数位) 52bits(尾数位)

这里写图片描述

3.2 浮点数的规格化

规格化目的:
(1)为了提高数据的表示精度
(2)为了数据表示的唯一性
(3)尾数为R进制的规格化: 绝对值大于或等于1/R

二进制原码的规格化数的表现形式:
正数 0.1xxxxxx
负数 1.1xxxxxx

补码尾数的规格化的表现形式:尾数的最高位与符号位相反:
正数 0.1xxxxxx
负数 1.0xxxxxx

这里写图片描述

【32位浮点数,IEEE754采用127做阶码的偏移量】
IEEE754规定这个偏移量为2^(e-1)-1,e为存储指数的位元的长度,在32位浮点数中存储指数的域有8位因此偏移量位2^(8-1)-1=127。这里根据标准,并没有使用移码作为阶码
**注意IEEE754中的移码和通常用的移码不相同,IEEE754用的是127移码,即在原数上加127
而不是通常的128移码(也就是所说的补码符号位取反)**

例1:

这里写图片描述

如果反过来求就是,
例2
这里写图片描述

例3
这里写图片描述

3.3 移码的来由

一个很有意思的问题
说了这么多,由移码当阶码,到移码-1到阶码,都不知道为什么,现在就来看看。
根据百度百科移码上说的:

移码(又叫增码)是符号位取反的补码,一般用做浮点数的阶码,引入的目的是为了保证浮点数的机器零为全0。

原因是:

用补码表示阶码的时候,当阶码无限小,产生了下溢的时候,阶码变成了0,那么这个浮点数的值变为了1。
而实际上这个数是无限接近于零的。那么我们就需要取出其中的 “-0“ 值作为机器零。

详细解释如下:
因为浮点数的表示是1.s * (2 ^ P), 所以浮点数0实际上是取无限接近于0,而不是其数值上确实得等于0

0的表示实际上是1.0 * (2 ^ -128),其中-128是阶码能表示的最小数

于是问题来了,如果用补码表示, -128实际上是10000000, 那么浮点数的0其数值就不能等于0. 所以采用移码.

但是IEEE754标准采用的是127移码,即在0的基础上加上127作为0,于是阶码表示范围是-127 - 128,而不是通常的-128 - 127

文章也基本上要告一段落了,这些应该已经可以对付日常理解,如果需要更深刻的理解,就需要查阅更多资料,如果博文中有不当的内容,欢迎批评指正,也欢迎讨论

附:
c++中,合法的浮点数表示形式:
(1)十进制小数形式。他有数字和小数点组成,必须有小数点。例如(123.)(123.0)(.123)。
(2)指数形式。如123e3。字母e(或E)之前必须有数字,e后面的指数必须为整数。
(3)规范化的指数形式里面,小数点前面有且只有一位非零的数字。如1.2345e8

详细了解补码,要看我这篇:补码与模

相关文章
|
11月前
|
监控 API 数据处理
淘宝商品详情API响应数据解析的详细说明
本内容介绍了淘宝商品详情API的调用与数据解析方法,涵盖商品基础信息、价格、库存、规格、促销、物流等关键数据的获取方式。提供了核心接口如taobao.item.get、taobao.itemprops.get、taobao.item.sku.get的功能说明及Python请求示例,适用于跨平台数据整合、价格监控、自动化运营等场景,并提示了字段兼容性、错误处理及数据更新等注意事项。
|
算法 数据处理 C语言
【数据结构与算法】快速排序(详解:快排的Hoare原版,挖坑法和双指针法|避免快排最坏时间复杂度的两种解决方案|小区间优化|非递归的快排)
【数据结构与算法】快速排序(详解:快排的Hoare原版,挖坑法和双指针法|避免快排最坏时间复杂度的两种解决方案|小区间优化|非递归的快排)
|
机器学习/深度学习 存储
数据结构(九)---并查集
数据结构(九)---并查集
739 5
|
网络安全 数据安全/隐私保护 异构计算
使用阿里云服务器实现内网穿透,ssh远程连接
使用阿里云服务器实现内网穿透,实现ssh远程连接
2805 0
使用阿里云服务器实现内网穿透,ssh远程连接
|
存储 XML 图形学
Unity保存数据
在Unity中保存场景数据涉及数据收集、序列化和存储。数据收集包括游戏对象的基本信息(如位置、旋转、缩放、名称和标签)及组件数据(如渲染、物理和自定义脚本组件)。接着,通过序列化将数据转换为可存储格式。示例代码展示了如何使用XML保存场景中的游戏对象及其属性。
|
存储 数据处理 UED
计算机随机存取存储器(RAM )
【8月更文挑战第4天】
7255 8
|
机器学习/深度学习 人工智能 编解码
深入探索AI文生语音技术的奥秘:从文本输入到逼真语音输出的全链条语音合成过程解析
【9月更文挑战第2天】深入探索AI文生语音技术的奥秘:从文本输入到逼真语音输出的全链条语音合成过程解析
 深入探索AI文生语音技术的奥秘:从文本输入到逼真语音输出的全链条语音合成过程解析
|
存储 算法
数据结构与算法学习十六:树的知识、二叉树、二叉树的遍历(前序、中序、后序、层次)、二叉树的查找(前序、中序、后序、层次)、二叉树的删除
这篇文章主要介绍了树和二叉树的基础知识,包括树的存储方式、二叉树的定义、遍历方法(前序、中序、后序、层次遍历),以及二叉树的查找和删除操作。
874 0
|
缓存 Java 数据库连接
Spring c3p0配置详解
【7月更文挑战第13天】
368 1
|
存储 搜索推荐 算法
快速排序算法详解
快速排序算法详解

热门文章

最新文章