char的特殊性:到底是有符号还是无符号是有编译器所规定的。
整数和浮点数的存储规则
整数的存储
根据国际标准,任意一个二进制浮点数v可以表示成下面的形式:
(-1)^S*M*2^E
(-1)^S表示符号位,当S=0,V为正数,当S=1,V为负数。
M表示有效数字,大于等于1,小于2.
2^E表示指数位。
例如:
5.5
的二进制位为(-1)^0 * 1.011 *2^2
一个5的二进制为101,5.5的二进制就为101.101,其中后面的0.1已经表示0.5了,所以二进制表现形式就为101.1也就是M,任何保证第一位为1情况下,后面还有两位,所以E就为2。
当小数点前面只有一位的时候E=-1。
再例如
9.0
1001.0
(-1)^0 *1.001 *2^3
浮点数的存储(同样是SME)
对于32位的浮点数(float)来说。
最高位是符号位S
接着的八位是指数E
剩下的23位位有效数字M
对于64位的浮点数来说。
最高位是符号位S
接下的11位是指数E
剩下的52位留给M
其中,M可以写成1.xxxxxx的形式,xxxxxx表示小数部分。
1
计算机内部保存M的时候,默认这个数的第一位总是1,因此可以被舍去只保留后面的xxxxxx部分。因此多了一个比特存储,以获取更高的精度。
2
E在8位下的取值范围位0-255,在11位的取值范围位0-2047,
E有可能出现负数。8位下的E需要加上127,11位下的E需要加上1023
比如,2^10的E是10,所以保存成32位浮点数的时候,必须保存成10+127=137,即10001001
int main()
{
float f = 5.5;
//101.1
//(-1)^0 * 1.011 *2^2
//S=0
//E=2
//M=1.011
//E + 127 = 129
//010000001
//然后再存M(存小数点后面的)
//010000001011
//位数不够,补0。
//0100 0000 1011 0000 0000 0000 0000 0000
//0x4 0 b 0 0 0 0 0
return 0;
}
然后,指数E从内存中取出来还可以分为三种情况:
1
E的11个/8个比特位不全为0或不全为1。
这时指数E的计算值减去127/1023得到真实值,再将有效数字M前加上第一位的1。
E为全0
这时浮点数的指数=1-127或者1-1023,即为真实值。
有效数字M不再加上第一位的1,而是还原成0.xxxxxxx的小数,也就是2^(负数)次方,表示的是很小的一个,无限接近于0的数字。
E为全1
表示+-无穷大的数字(正负取决于符号位S)
int main()
{
int n = 9;
//
//00000000000000000000000000001001
//0 00000000 00000000000000000001001
//1位 8位 23位
//E = -126
//M = 0.00000000000000000001001
//S = 0
//(-1)^0 * 0.00000000000000000001001 * 2^-126
//1 * 0.00000000000000000001001 * 2^-126
float* pFloat = (float*)&n;//int*
printf("n的值为:%d\n", n);//9
printf("*pFloat的值为:%f\n", *pFloat);//0.000000
*pFloat = 9.0;
//9.0
//1001.0
//1.001 * 2^3
//(-1)^0 * 1.001 * 2^3
//S = 0
//M = 1.001
//E = 3 +127
//0 10000010 --130 然后后面追加M
//0 10000010 00100100000000000000000
printf("num的值为:%d\n", n);//1,091,567,616
printf("*pFloat的值为:%f\n", *pFloat);//9.0
return 0;
}