操作系统系列十 —— 浮点数存储和定点化逻辑

往期地址:

本期主题:
浮点数存储和定点化逻辑



背景:
在工作中遇到一些寄存器的定点化问题,发现这个与浮点数的存储逻辑有一定相关性,因此把这块知识整理一下。

1.二进制小数

目前我们所用的浮点数的标准是IEEE-754标准。

IEEE是电气和电子工程师协会,是一个包括所有电子和计算机技术的专业团队。

需要理解浮点数,首先需要理解二进制小数。
首先我们可以看一下传统的十进制表示法,例如有一个数用十进制表示为:

d m d_m dm d m − 1 d_{m-1} dm1 d m − 2 d_{m-2} dm2 d 1 d_1 d1 d 0 d_0 d0 . d − 1 d_{-1} d1 d − n d_{-n} dn

那么这个数的实际表示的值为:

d = ∑ i = − n m 1 0 i ∗ d i d = \sum_{i=-n}^m10^i*d_i d=i=nm10idi

那么这个数如果用二进制表示的话,其实就是:

d = ∑ i = − n m 2 i ∗ d i d = \sum_{i=-n}^m2^i*d_i d=i=nm2idi
例如, 101.1 1 2 101.11_2 101.112 实际上就是: 1 ∗ 2 2 + 1 ∗ 2 0 + 1 ∗ 2 − 1 + 1 ∗ 2 − 2 = 5 3 4 1*2^2+1*2^0+1*2^{-1}+1*2^{-2}=5\frac{3}{4} 122+120+121+122=543

从上面的公式也能知道,想用二进制表示一个小数,精度取决于用多少位来进行表示,例如

二进制表示值精度十进制
0. 0 2 0.0_2 0.02 1 2 \frac{1}{2} 21 0. 0 10 0.0_{10} 0.010
0.0 1 2 0.01_2 0.012 1 4 \frac{1}{4} 41 0.2 5 10 0.25_{10} 0.2510
0.0100 1 2 0.01001_2 0.010012 1 32 \frac{1}{32} 321 9 32 = 0.2812 5 10 \frac{9}{32}=0.28125_{10} 329=0.2812510

2.浮点数存储

前面所描述的定点表示法,无法很有效地表示非常大的数字,例如表达式 5 ∗ 2 100 5*2^{100} 52100,需要有100个0才能表达
因此IEEE754标准用:

V = ( − 1 ) s ∗ M ∗ 2 E V=(-1)^s*M*2^E V=(1)sM2E 来表示一个数

其中:

  • 符号(sign),s代表符号,s=1代表负数,s=0代表正数
  • 尾数(significand),M是一个二进制小数,范围是1~2
  • 阶码(exponent),E代表2的E次幂

因此我们可以将浮点数划分成3个字段,分别进行编码:

  • 单独的符号s直接编码
  • k位的阶码编码, e x p = e k − 1 e k − 2 . . . . e 0 exp=e_{k-1}e_{k-2}....e_0 exp=ek1ek2....e0
  • n位小数字段编码, f r a c = f n − 1 f n − 2 . . . f 0 frac=f_{n-1}f_{n-2}...f_0 frac=fn1fn2...f0

在单精度浮点表达时,按照以下的格式进行表达:
在这里插入图片描述
根据指数位exp的内容,又能将浮点数的存储分为 规格化非规格化存储 以及特殊值

规格化:
在这里插入图片描述
非规格化:
在这里插入图片描述

1.规格化值

当exp既不全为0,也不全为1时,这种情况下,阶码被解释为以bias形式表示的有符号整数,也就是说

阶码的值是 E = e - bias,其中e是无符号数,表示为 e k − 1 e k − 2 . . . e 1 e 0 e_{k-1}e_{k-2}...e_1e_0 ek1ek2...e1e0,bias是一个等于 2 k − 1 − 1 2^{k-1}-1 2k11的值(单精度是127,双精度是1023)

小数字段frac被描述为小数值f, 0 ≤ f < 1 0\leq f< 1 0f<1,其二进制表示为 0. f n − 1 . . . f 1 f 0 0.f_{n-1}...f_1f_0 0.fn1...f1f0

尾数 M=1+f, 1 ≤ M < 2 1\leq M< 2 1M<2,由于M的第一位必定是0,所以我们就不需要显式的表达它

规格化值的一个关键在于:
可以通过调整阶码E,使得尾数M的范围在有效范围内

例如从1.25->2.25,1.25用二进制表达为: 1.2 5 10 = 1.0 1 2 1.25_{10} = 1.01_2 1.2510=1.012,而 2.2 5 10 = 10.0 1 2 2.25_{10} = 10.01_2 2.2510=10.012,将阶码增加1变为 1.00 1 2 1.001_2 1.0012,因此1.25和2.25的差异在于2.25的阶码比1.25大1,并且小数部分,2.25是1.25的 1 2 \frac{1}{2} 21

2.非规格化值

阶码域全为0时,所表达的是非规格化形式,这种情况下

阶码值是 E= 1 - bias
尾数值是M = f,不包含隐式的开头1

3.示例

假设现在有一个8位浮点格式,其中阶码位为4位,小数位为3位
那么就有

b i a s = 2 4 − 1 − 1 = 7 bias = 2^{4-1}-1=7 bias=2411=7

在这里插入图片描述

3.代码测试

实验目的:将输入浮点数的sign、exp、frac都打印出来,验证猜想

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

typedef struct _my_str_t
{
    union 
    {
        float val;
        struct _my_union_str_t
        {
            uint32_t frac : 23;
            uint32_t exp  : 8;
            uint32_t sign : 1;
        } union_str_t;
    };
} my_str_t;

int main(void)
{
    my_str_t my_str = { 0 };
    printf("Please input test float val :\r\n");
    scanf("%f", (float *)&(my_str.val));

    printf("sign is 0x%x, exp is 0x%x (%d), frac is 0x%x\r\n", my_str.union_str_t.sign, my_str.union_str_t.exp, my_str.union_str_t.exp, my_str.union_str_t.frac);

    return 0;
}

测试结果:
在这里插入图片描述
在这里插入图片描述

结果也可以参考这里:
IEEE 754 converter

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值