赞
踩
IEEE754提供了二进制存储十进制浮点数的具体标准,分别为单精度型,双精度型,延伸单精度型,延伸双精度型。
符号位S:31位,0代表正,1代表负
指数位E:23-30位
尾数位F:0-22位
一个十进制浮点数可以表示为:
尾数的小数点放在第一位和第二位之间,且保证第一位不为0,故尾数始终表示为1.****,这个处理过程称为规范化(normailzed)。
规范化之后,尾数始终表示为1.****,存储尾数时,省略前面的1,只记录小数点之后的部分,不够23位的在低位补0。
IEEE754规定,单精度浮点数的指数位用于表示[-127, 128]范围内的指数(双精度的偏移量为1023),浮点型的指数位都有一个固定的偏移量(bias),指数 + 偏移量 = 非负整数。因此实际计算需要减去这个偏移量B。
现在一个十进制数可以表示为:
根据IEEE754的规定, 按照尾数位隐藏的整数部分是 1. 还是0. 可以将浮点数划分为两类: normal number(规格数) 和 subnormal number(非规格数)
尾数位隐藏的整数部分为1.的数称为规格数,大部分数都为规格数,存储尾数时,省略前面的1,只存储小数点之后的部分;
尾数位隐藏的整数部分为0.的数称为非规格数,为了表示subnormal number, IEEE754规定: 如果将指数位全部填充为0, 则表示这个数是个非规格数。
特殊数
特殊数分为两种: 无穷(infinity)和NaN(not a number)
无穷
当指数位全为1,且尾数位全为0时,就表示为无穷,根据符号位来确定是正无穷还是负无穷,分别记做+infinity和-infinity,由于浮点数有其取值范围,超过范围就被记作无穷,关于浮点数的取值范围下面再说。
NAN
当指数位全为1,且尾数位不全为0,就表示为NaN,NaN没有+/-之分,统称NaN。
存储双精度浮点数需要64个比特位,其中最高位仍是符号位S,而指数位E提升到了11位,尾数位F提升到了52位。
这里有个可以方便实现十进制数到32位浮点数转换的网站网站https://www.h-schmidt.net/FloatConverter/IEEE754.html可惜该网站暂时不能计算双精度64位,不过借助ChatGPT可以方便的写一段代码帮助查看,借助菜鸟的c在线编译网站可以运行查看。
- #include <stdio.h>
-
- // 联合体用于类型转换
- typedef union {
- double num;
- unsigned long long bits;
- } DoubleBits;
-
- void printBinary(double num) {
- DoubleBits converter;
- converter.num = num;
-
- // 从最高位到最低位逐位输出
- for (int i = (sizeof(converter.bits) * 8) - 1; i >= 0; --i) {
- unsigned long long mask = 1ULL << i; // 构造掩码
-
- // 使用掩码进行与运算判断该位是0还是1
- int bit = (converter.bits & mask) ? 1 : 0;
-
- printf("%d", bit);
-
- if (i % 8 == 0) {
- printf(" "); // 每8位添加一个空格
- }
- }
-
- printf("\n");
- }
-
- int main() {
- double num = 1.111; // input your number
-
- printf("二进制表示为:");
- printBinary(num);
-
- return 0;
- }
如上所述,IEEE754规定,当指数位全部为0或者全部为1时,用于表示两种特殊状态的数: subnormal number 和 non-number,所以现在可以得到如下示意图, 以32位单精度浮点数为例:
对于指数,由于指数部分无法取到全0或者全1,减去偏置(127)之后,取值范围为[-126,127]。
对于尾数,规范数尾数前时钟隐藏整数位1,因此尾数的取值范围其实是[1.000...,1.111...],约等于十进制的[1,2),左闭右开。
在有了指数和尾数的取值范围之后,整个浮点的取值范围也就随之确定了,根据运算规则,32为浮点的取值范围为: ±[1,2) × 2^[-126,127] = (-2 × 2^127,-1 × 2^-126] ∪ [1 × 2^-126,2 × 2^127)
转换成以10为底之后:
取一个更容易表示的子集,就是我们常见的32位float的取值范围:
十进制的四舍五入,大于0.5即进位1,小于0.5则舍掉。
朝零舍入即朝数轴零点方向舍入,直接截位即可。
对于正数,多余位为0则直接截位,不全为0则进1;
对于负数,无论多余位是多少直接截位;
对于负数,多余位为0则直接截位,不全为0则进1;
对于正数,无论多余位是多少直接截位;
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。