C语言之浮点数的存储

  • 2020 年 2 月 19 日
  • 筆記

欢迎关注VxWorks567

如转发,请标明出处!

C语言中,有两种类型的浮点数:32位的float和64位的double,而在计算机中存储的是用二进制的科学计数法(即基数为2)表示的值

例如100=1100100B=1.1001B*26,123.456=1111011.0111010010111100011010100111111011111001110111B=1.1110110111010010111100011010100111111011111001110111B*26

既然基数固定为2,尾数的整数部分固定为1,那存储时就可以省略掉它俩了,只需要存储另外三个信息:正负符号+指数+尾数的小数部分

float:符号占1位,指数占8位,尾数小数占23位;

double:符号占1位,指数占11位,尾数小数占52位

不过指数也有正负,因此存储时加个偏移来表示。float用8位表示指数,偏移就是127;double用的是11位,那偏移就是1023

看看123.456用float是如何存储的:因为是正数,符号位用0;指数是6,加上偏移127后,133=10000101B;尾数的小数部分的前23位是11101101110100101111001(第24位是1,因此需要进位),拼接成32位数就是01000010111101101110100101111001B=1123477881

将C语言中的定义转换为汇编验证一下

再看一个纯小数的存储,例如0.00123456,这次倒着推导一下

计算机中存储的是983683318,转换为二进制就是00111010101000011101000011110110B。其中第一个0表示正值;挨着的8位01110101B=117,表示指数为(117-127)=-10;最后的23位表示尾数的小数部分,前面加上整数部分的1,再左移23位之后就是101000011101000011110110B=10604790。那么原值就是10604790右移23位,再左移-10位,即10604790右移33位。而233=8589934592。所以原值就是10604790/8589934592=0.0012345600407571,可见前10位小数都是正确的,精度还可以

最后试个double的123.456

计算机里存储的是两个32位数:1079958831(高)、446676599(低)

二进制就是:01000000010111101101110100101111,00011010100111111011111001110111B。其中第一个0表示正值;指数位是10000000101B=1029,表示指数为(1029-1023)=6;最后是52位尾数,前面加上整数部分的1,再左移52位之后,11110110111010010111100011010100111111011111001110111B=8687443681197687。因此,原值就是8687443681197687右移52位,再左移6位,即右移46位,而246=70368744177664。

8687443681197687/70368744177664=123.456

好吧,double的精度确实高,比float表示的准多了!

我是泰山,专注VX 15年!

一起学习,共同进步!