小数在内存中如何存储?
2022-11-16 14:27:05 4 举报
AI智能生成
小数在内存中如何存储
作者其他创作
大纲/内容
任意一个二进制浮点数 V = (-1)^S * M * 2^E
(-1)^S 表示符号位:s=0,正数,s=1,负数
M 表示有效数字,大于等于1,小于2
2^E 表示指数位
(-1)^S 表示符号位:s=0,正数,s=1,负数
M 表示有效数字,大于等于1,小于2
2^E 表示指数位
举例:
数字:9.0
二进制:1001.0
(-1)^0 * 1.001 * 2^3
S = 0,M = 1.001 , E = 3
数字:9.0
二进制:1001.0
(-1)^0 * 1.001 * 2^3
S = 0,M = 1.001 , E = 3
举例:
数字:5.0
二进制:101.0
(-1)^0 * 1.01 * 2^2
S = 1, M = 1.01 , E = 2
数字:5.0
二进制:101.0
(-1)^0 * 1.01 * 2^2
S = 1, M = 1.01 , E = 2
举例
数字:0.5
二进制:0.1
(-1)^0 * 1.0 * 2^(-1)
S = 0 ,M = 1.0 , S = -1
数字:0.5
二进制:0.1
(-1)^0 * 1.0 * 2^(-1)
S = 0 ,M = 1.0 , S = -1
整数前面补0,小数后面补0
单精度浮点数存储模型
float类型:32位的浮点数
S: 1bit
E: 8bit
M:23bit
E: 8bit
M:23bit
E:
为无符号数(unsigned int)
如果E是8位,取值范围 0~255
如果E是11位,取值范围0~2047
为无符号数(unsigned int)
如果E是8位,取值范围 0~255
如果E是11位,取值范围0~2047
保存:
科学计数法中E是可以出现负数的,
存入内存时E的真实值必须再加上一个中间数
对于8位的E,这个中间数是127
对于11位的E,这个中间数是1023
比如 2^10中E是10,保存为32位浮点数时,
必须保存为10 + 127 = 137,即10001001
科学计数法中E是可以出现负数的,
存入内存时E的真实值必须再加上一个中间数
对于8位的E,这个中间数是127
对于11位的E,这个中间数是1023
比如 2^10中E是10,保存为32位浮点数时,
必须保存为10 + 127 = 137,即10001001
取值
E不全为0且不全为1
指数E减去127(或1023),得到真实值
再将有效数字M前加上第一位的1
再将有效数字M前加上第一位的1
E全为0
即E等于-127或者-1023,有效数字M不再加上第一位的1,
而是还原为0.xxx的小数。这样做是为了表示 数字时接近于0的很小的数字
而是还原为0.xxx的小数。这样做是为了表示 数字时接近于0的很小的数字
E全为1
这是如果有效数字M全为0,就表示 正负 无穷大,(正负取决于符号位s)
M:
因为M的第一位总是1,因此在保存的时候会舍去。等读取的时候再把第一位的1加上
比如32位浮点数,留给M只有23位,第一位的1舍去,等于可以保存24位有效数字
因为M的第一位总是1,因此在保存的时候会舍去。等读取的时候再把第一位的1加上
比如32位浮点数,留给M只有23位,第一位的1舍去,等于可以保存24位有效数字
举例
1、数字5.5
2、二进制:101.1
3、即 (-1)^0 * 1.011 * 2^2
S = 0 , E = 2 , M = 1.011
4、E为2,2加上中间数127,2+127=129
5、转为二进制:
S E M
0 10000001 011(不足32位,因为是小数,在后面补0)
6、再拆为16进制
0100 0000 1011 0000 0000 0000 0000 0000
即 0x 40 b0 00 00 即 内存中保存的内容
1、数字5.5
2、二进制:101.1
3、即 (-1)^0 * 1.011 * 2^2
S = 0 , E = 2 , M = 1.011
4、E为2,2加上中间数127,2+127=129
5、转为二进制:
S E M
0 10000001 011(不足32位,因为是小数,在后面补0)
6、再拆为16进制
0100 0000 1011 0000 0000 0000 0000 0000
即 0x 40 b0 00 00 即 内存中保存的内容
双精度浮点数存储模型
double类型:64位浮点数
S:1bit
E:11bit
M:52bit
E:11bit
M:52bit
测试代码
#include <stdio.h>
// 任意一个二进制浮点数v都可以表示成下面的形式
// v = (-1)^s *M *2^E
// (-1)^s 符号位,s=0时,正数;s=1时,负数
// M标识有效数字, >=1,<2
// 2^E表示指数位
// 单精度:
// 双精度:
int main()
{
// 关键点1:float 后面有6位小数
// 关键点2:
int n = 9;
// 00000000 00000000 00000000 00001001
float *p = (float *)&n;
// 如果强转为 float*类型
// 0 00000000 000000000000...1001
// s e m
printf("n==d=1=%d\n",n); // 9
printf("n==f=1=%f\n", *p); // 0.000000 ,e全0,无线小,所以输出为0
*p = 9.0;
// 二进制:1001.0
// S = 0 , E = 3 , M = 1.001
// float保存为为 : 0 10000010 001 0000...共32位
// 01000001 00010000 00000000 00000000 即 1091567616
printf("n==d=2=%d\n", n); // 1091567616
printf("n==d=2=%f\n", *p); // 9.000000
return 0;
}
// 任意一个二进制浮点数v都可以表示成下面的形式
// v = (-1)^s *M *2^E
// (-1)^s 符号位,s=0时,正数;s=1时,负数
// M标识有效数字, >=1,<2
// 2^E表示指数位
// 单精度:
// 双精度:
int main()
{
// 关键点1:float 后面有6位小数
// 关键点2:
int n = 9;
// 00000000 00000000 00000000 00001001
float *p = (float *)&n;
// 如果强转为 float*类型
// 0 00000000 000000000000...1001
// s e m
printf("n==d=1=%d\n",n); // 9
printf("n==f=1=%f\n", *p); // 0.000000 ,e全0,无线小,所以输出为0
*p = 9.0;
// 二进制:1001.0
// S = 0 , E = 3 , M = 1.001
// float保存为为 : 0 10000010 001 0000...共32位
// 01000001 00010000 00000000 00000000 即 1091567616
printf("n==d=2=%d\n", n); // 1091567616
printf("n==d=2=%f\n", *p); // 9.000000
return 0;
}
0 条评论
下一页