乐趣区

关于c:C进阶3浮点数的秘密

Summary

1)浮点数在内存中的存储形式:

类型 符号位 指数 尾数
float 1 位(第 31 位) 8 位(第 23-30 位) 23 位(第 0 -22 位)
double 1 位(第 63 位) 11 位(第 52-62 位) 52 位(第 0 -51 位)

2)float 与 double 类型的数据在计算机外部的 表示法是雷同的 ,然而因为 所占存储空间大小的不同 ,其别离可能 示意的数值范畴和精度不同

3)浮点数的转换
如:浮点数 -8.25 的二进制转换,float 类型:
1. 符号位 :1(正数)
2. 绝对值二进制:1000.01(整数局部的指数顺次为 0,1,2…; 正数局部的指数一次为 -1,-2,-3…)
3. 迷信计数法:1.00001 * 23,指数为 3
4. 指数 + 偏移:3 + 127 = 130 <–> 1000 0010(float 的 指数占 8 位
5. 尾数:尾数局部为 00001,占 23 位,有余的 前面补 0 :00001 0000 0000 0000 0000 00
6. 最终:二进制为:1 1000 0010 00001000000000000000000(符号位 + 指数 + 尾数);用 16 进制示意为:0xc1040000

留神

  • 对于 float 类型,指数的偏移为 +127;对于 double 类型,指数的偏移为+1023。尾数局部,有余的位数前面 补 0
  • 通过如下 指针 形式,能够 取得一段内存中的二进制位

    unsigned int* p = (unsigned int*)&val;
    printf("%08x", *p);   // %08x 示意以 16 进制的模式来打印内存里的值

4)float 能示意的 具体数字的个数与 int 雷同 (都占用 4 个字节,一共 32 个 bit 位,所以最多就 2 32排列组合形式 ,即最多能示意 2 32 个数)

5)float 的表示法是 不准确 的,所以能示意的范畴比 int 大。因为 float 的值不准确,所以对于一个 float 值,间接打印的数据可能有偏差 ;同时对于浮点数的运算, 不能间接和 0 比拟

6)因为 float 的 内存表示法比 int 简单 ,所以 float 的 运算速度 比 int

浮点数的机密

1、浮点数在内存中的存储形式

类型 符号位 指数 尾数
float 1 位(第 31 位) 8 位(第 23-30 位) 23 位(第 0 -22 位)
double 1 位(第 63 位) 11 位(第 52-62 位) 52 位(第 0 -51 位)

float 与 double 类型的数据在计算机外部的 表示法是雷同的 ,然而因为 所占存储空间大小的不同 ,其别离可能 示意的数值范畴和精度不同

2、浮点数的转换

如:浮点数 -8.25 的二进制转换,float 类型:
1. 符号位 :1(正数)
2. 绝对值二进制:1000.01(整数局部的指数顺次为 0,1,2…; 正数局部的指数一次为 -1,-2,-3…)
3. 迷信计数法:1.00001 * 23,指数为 3
4. 指数 + 偏移:3 + 127 = 130 <–> 1000 0010(float 的 指数占 8 位
5. 尾数:尾数局部为 00001,占 23 位,有余的 前面补 0 :00001 0000 0000 0000 0000 00
6. 最终:二进制为:1 1000 0010 00001000000000000000000(符号位 + 指数 + 尾数);用 16 进制示意为:0xc1040000

float f = -8.25f;  // f 指明为 float 类型
unsigned int* p = (unsigned int*)&f; // 用指针指向该浮点数的内存,并 '以无符号整型数来示意'
printf("0x%08X\n", *p); // %08X,示意以 16 进制大写的模式来打印值,通常 '用来打印内存的二进制位'

// 输入为:0xC104 0000,和笔算后果统一。

如果已知一个 32 位二进制示意一个浮点数,则推算后果和下面相同

3、浮点数深刻了解

int 类型的范畴:[-231, 231-1]
float 类型的范畴:[-3.4 x 1038, 3.4 x 1038]

问题:为什么 int 和 float 都占用 4 个字节的内存,而 float 却比 int 的范畴大的多呢?
解析:

  • float 能示意的 具体数字的个数与 int 雷同 (都占用 4 个字节,一共 32 个 bit 位,所以最多就 2 32排列组合形式 ,即最多能示意 2 32 个数)
  • float 可示意的数字之间是不间断的,有间隙的
  • float 只是一种 近似 的表示法,不能作为准确数来应用
  • 因为内存表示法绝对简单,float 的 运算速度 比 int 慢的多

另:double 和 float 的内存表示法是雷同的,所以也是不准确的。因为 double 占用的字节数比 float 多,所以 double 示意的精度比 float 高。

float f1 = 3.1415f;
float f2 = 123456789;

// 打印小数点后 10 位
printf("%0.10f\n", f1);  // 3.1414999962
printf("%0.10f\n", f2);  // 123456792.0000000000

本文总结自“狄泰软件学院”唐佐林老师《C 语言进阶课程》。
如有错漏之处,恳请斧正。

退出移动版