浮点数的二进制表示
浮点数在C/C++中对应 float 和 double 类型,我们有必要知道浮点数在计算机中实际存储方式。
IEEE754规定:
单精度浮点数字长32位,尾数长度23,指数长度8,指数偏移量127;双精度浮点数字长64位,尾数长度52,指数长度11,指数偏移量1023;约定小数点左边隐含有一位,通常这位数是1,所以上述单精度尾数长度实际为24(默认省略小数点左边的1则为23),双精度尾数长度实际为53(默认省略小数点左边的1则为53)。
知识点一:
IEEE754 单精度(32位)的二进制排列规则:符号位S(1位,0为正数,1为负数) + 阶码E(8位) + 尾数M(23位)。
IEEE754 双精度(64位)的二进制排列规则:符号位S(1位,0为正数,1为负数) + 阶码E(11位) + 尾数M(52位)。
知识点二:
单精度的偏置常数为127(固定值),阶码 = 127 + 阶(左移为正数,右移为负数)。
双精度的偏置常数为1023(固定值),阶码 = 1023 + 阶(左移为正数,右移为负数)。
一、float 单精度浮点数
IEEE754 标准中规定 float 单精度浮点数在机器中用32位表示,其中用 1 位表示数字的符号,用 8 位来表示指数,用23 位来表示尾数,即小数部分。
一个由IEEE745制的32位浮点数由三部分组成
组成部分 | 位数 | 含义 |
---|---|---|
符号位 | 1位 | 0为正,1为负 |
指数位 | 2~9位 | 类比十进制的科学计数法,此处以2为底,指数位为幂。注意还需要加上127的偏移量 |
尾数位 | 10~32位 | 省略了1. 实际为1.(尾数位),类似小数的二进制写法 |
核心逻辑:
这种设计允许浮点数以不同的精度级别覆盖广泛的值。用于这种表示的公式是:
二、double 双精度浮点数
对于 double 双精度浮点数在机器中用64位表示,其中,用 1 位表示符号,用 11 位表示指数,52 位表示尾数,其中指数域称为阶码。
在各种数据类型中,浮点数能够以高精度表示各种值。通常,浮点数使用n位来存储数值。这些 n 位 进一步分为三个不同的组成部分:
- 符号:符号位指示数字的正数或负数。它使用一位,其中 0 表示正数,1 表示负数。
- 指数:指数是一段位,表示基数(在二进制表示中通常为 2)的幂。指数也可以是正数或负数,允许数字表示非常大或非常小的值。
- 有效数/尾数:剩余位用于存储有效数,也称为尾数。这代表数字的有效数字,表示精确度。数字的精度在很大程度上取决于有效数字的长度。
- float 类型可以表示正零值和负零值
- mantissa从左到右第N位表示2-N,例如1.5的二进制表示。
int64与相等float64的二进制关联
二进制 | 数值 |
0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0010 0010 1011 | 555 |
0100 0000 1000 0001 0101 1000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 | 555.0 |
int64 最高非零位以后的二进制位 === float64 mantissa,所以float64可以不损失精度表示的最大 int64 范围是-253 ~ 253,253+1就没法表示了。然而,诸如253+2一类的 int64 仍然可以不损失精度地用 float64 表示。
例1:将十进制数 33.758 转换为IEEE754的单精度浮点数格式表示
步骤①:将整数部分整除以2,取余数部分倒序排列
33 / 2 = 16 余数为1
16 / 2 = 8 余数为0
8 / 2 = 4 余数为0
4 / 2 = 2 余数为0
2 / 2 = 1 余数为0
1 / 2 = 0 余数为1
得到整数部分二进制为 1000 01
步骤②:将小数部分乘以2,取商的整数部分正序排列
( 一直乘 2 ,遇到 1 退出;如果乘 2 之后的数字大于 1,则减去 1 )
0.758 * 2 = 1.516 取商的整数部分1 1.516 - 1 = 0.516
0.516 * 2 = 1.032 取商的整数部分1 1.032 - 1 = 0.032
0.032 * 2 = 0.064 取商的整数部分0
0.064 * 2 = 0.128 取商的整数部分0
0.128 * 2 = 0.256 取商的整数部分0
0.256 * 2 = 0.512 取商的整数部分0
0.512 * 2 = 1.024 取商的整数部分1 1.024 - 1 = 0.024
0.024 * 2 = 0.048 取商的整数部分0
0.048 * 2 = 0.096 取商的整数部分0
0.096 * 2 = 0.192 取商的整数部分0
0.096 * 2 = 0.384 取商的整数部分0
0.384 * 2 = 0.768 取商的整数部分0
0.768 * 2 = 1.536 取商的整数部分1 1.536 - 1 = 0.536
0.536 * 2 = 1.072 取商的整数部分1 1.072 - 1 = 0.072
0.072 * 2 = 0.144 取商的整数部分0
0.144 * 2 = 0.288 取商的整数部分0
0.288 * 2 = 0.576 取商的整数部分0
0.576 * 2 = 1.152 取商的整数部分1 1.152 - 1 = 0.152
0.152 * 2 = 0.304 取商的整数部分0
尾数可以取23位,但因小数点后第一位"1"不显式地表示出来,这样可用23位来表示24位尾数,因前面整数已经占6位,则小数部分只能取18位,即1100 0010 0000 1100 01
故33.758转换为二进制为:1000 01.1100 0010 0000 1100 01
步骤③:小数点向左移,直到整数部分为1,即1.00001110000100000110001 * 2 ^ 5
至此得到阶为5,阶码 = 5 + 127 = 132 转换成二进制为1000 0100,即阶码E = 1000 0100,尾数M为1.后面的数,即:0000 1110 0001 0000 0110 001
步骤④:根据数值的正负定义符号位
33.758 > 0 所以符号位S为0
步骤⑤:根据知识点一进行数值组装
得到IEEE754的单精度浮点数格式为
符号位S(1位,0为正数,1为负数) + 阶码E(8位) + 尾数M(23位)
0 1000 0100 0000 1110 0001 0000 0110 001
例2:将用IEEE754二进制表示的32位浮点数转成它所表示的十进制数
参考:
IEEE754介绍
IEEE754解析方法
关于IEEE754单精度(32位)的计算步骤(超详细)_ieee754标准计算公式-CSDN博客
模型量化2:最常用的数据类型:float32 (FP32)、float16 (FP16) 、 bfloat16 (BF16)【IEEE754制32位浮点数转换为十进制】-CSDN博客
十进制转二进制定点小数MATLAB代码_matlab如何把十进制转为位数可控的二进制小数-CSDN博客