float存储格式及FPU

float存储格式及FPU  

浮点数用科学计数法的形式存储, 即分成符号位, 底数位和指数位
如 10.0 的二进制表示为 1010.0, 科学表示法表示为: 1.01exp110, 即 (1+0*1/2+1*1/4)*2^3. 小数点每左移一位指数要加1, 每右移一位指数要减1.

其存储格式符合IEEE标准, 即

数据格式        符号位     底数位     指数位


单精度 float     1        23          8


双精度 double    1        52         11


扩展精度         1        64         15

存储顺序为: 符号位 指数位 底数位, 由于底数的个位必为1, 因此个位和小数点就不存储. 指数位的高位也是符号位, 不过为1表示正, 0表示负.

float 因有 8 bits, 所以能表示的有 2 的 256 次方,
      但因為指數應可正可負,
      所以 IEEE 規定, 此處算出的次方須減去 127 才是真的指數,
      所以 float 的指數可從-126 到 128.
      double 型態有 11 bits, 算出的值須減去 1023,
      所以double 的指數可從 -1022 到 1024.
      底数   (mantissa):      
    〈特例〉0   不能以 2 的次方表示
      float : 00 00 00 00
      double: 00 00 00 00 00 00 00 00

由此可推断浮点数的精度. 单精度的底数只存储23位, 即最小一位为 1/2^23, 故精度为 1/2^23 = 1.19209e-7, 可精确到小数点后6位; 双精度的底数存储52位, 最小位为 1/2^52, 精度为 1/2^52 = 2.22045e-16, 能精确到小数点后15位.

双精度的最大值约为 2*2^(2^10-1), 约为1.79e308

 

 


关于FPU:
(gdb) list 1,80
1        #include <stdio.h>
2        int main(int argc,char **argv)
3        {
4        float val = 1000;
5        int   ival = val;
6        printf("%f/n",val);
7        printf("%d/n",ival);
8        }
(gdb) display/i $pc
(gdb) break main
Breakpoint 1 at 0x8048365: file float.c, line 4.
(gdb) r
Starting program: /home/lsm1982/float

Breakpoint 1, main () at float.c:4
4        float val = 1000;
1: x/i $pc   0x8048365 <main+17>:         mov     $0x447a0000,%eax
(gdb) si
0x0804836a       4        float val = 1000;
1: x/i $pc   0x804836a <main+22>:         mov     %eax,0xfffffff4(%ebp)
(gdb)
5        int   ival = val;
1: x/i $pc   0x804836d <main+25>:         flds    0xfffffff4(%ebp)
(gdb)
0x08048370       5        int   ival = val;
1: x/i $pc   0x8048370 <main+28>:         fnstcw 0xffffffea(%ebp)
(gdb)
0x08048373       5        int   ival = val;
1: x/i $pc   0x8048373 <main+31>:         movzwl 0xffffffea(%ebp),%eax
(gdb)
0x08048377       5        int   ival = val;
1: x/i $pc   0x8048377 <main+35>:         mov     $0xc,%ah
(gdb)
0x08048379       5        int   ival = val;
1: x/i $pc   0x8048379 <main+37>:         mov     %ax,0xffffffe8(%ebp)
(gdb)
0x0804837d       5        int   ival = val;
1: x/i $pc   0x804837d <main+41>:         fldcw   0xffffffe8(%ebp)
(gdb)
0x08048380       5        int   ival = val;
1: x/i $pc   0x8048380 <main+44>:         fistpl 0xfffffff8(%ebp)
(gdb)
0x08048383       5        int   ival = val;
1: x/i $pc   0x8048383 <main+47>:         fldcw   0xffffffea(%ebp)
(gdb)
6        printf("%f/n",val);
1: x/i $pc   0x8048386 <main+50>:         flds    0xfffffff4(%ebp)
看来强制类型转换并不只是将存储的
的二进制代码进行不同类型的解释,还有其他可能的情况。
FPU也有其在处理器中的特殊性

### STM32 中 `float` 类型的使用说明 #### 浮点数的数据表示 在STM32微控制器中,浮点数遵循IEEE 754标准单精度格式。这种格式占用32位存储空间,分为三个部分:1位符号位、8位指数位以及23位尾数位[^1]。 对于具体的数值范围而言,正负最大值大约为±3.4×10^38之间;而最小可分辨正值接近于1.2×10^-38。当涉及到非常小或大数量级的操作时需要注意溢出风险。 #### 编程指南 为了提高程序效率,在编写涉及大量浮点运算代码前应当考虑编译器选项设置。某些情况下可以选择开启硬件FPU支持来加速计算过程。如果目标芯片确实配备了浮点单元,则应该确保启用了相应功能并选择了合适的库版本以便充分利用其性能优势。 另外值得注意的是,尽管C语言本身提供了良好的跨平台兼容性保障机制,但在不同架构间移植含有复杂数学函数调用的应用软件仍需谨慎处理潜在差异问题。 ```c // 启动 FPU 支持(假设使用 HAL 库) __HAL_RCC_SYSCFG_CLK_ENABLE(); __HAL_RCC_FPU_CLK_ENABLE(); // 定义一个简单的带有浮点参数的函数 void processFloat(float input) { float result; // 进行一些基本算术操作 result = input * 2.0f + 3.14f; // 执行其他逻辑... } ``` #### 精度考量 考虑到资源受限环境下的嵌入式系统特点,开发者往往会在精确性和执行速度之间寻找平衡点。虽然双精度(`double`)可以提供更高的准确性,但对于大多数应用场景来说单精度已经足够满足需求,并且能够节省宝贵的RAM和ROM资源消耗。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值