众所周知C语言中浮点数占四个字节,无论在32位或者64位机器上。不免会发出疑问四个字节是怎么计算出小数的呢?其实物理存放还是按照整型存放的。
IEEE 754 单精度浮点数格式
浮点数在计算机中是使用 IEEE 754 标准进行表示的。在 IEEE 754 标准中,32 位的单精度浮点数(float 类型)被分为三个部分:
符号位 (S):1 位,用来表示数值的符号,0 表示正数,1 表示负数。
指数位 (E):8 位,用来表示指数部分,并采用偏移量表示法(偏移量是 127)。
尾数位 (M):23 位,用来表示有效数字(也叫做"分数部分"),通常称为"尾数"或"有效数字"部分。
如何计算浮点数的值
浮点数的值的计算方式如下:
result = [(-1)^S]*[(2)^(E-127]*(1+M)
详细步骤:
符号位 (S):如果符号位为 0,表示正数;如果符号位为 1,表示负数。
指数位 (E):8 位的指数部分存储的是一个有偏的数值,即实际指数值 = 存储值 - 127。这个偏移量(127)允许指数表示负数和正数。
尾数位 (M):尾数部分是 23 位二进制数,存储的是一个小数部分,实际上是 1.M(1 加上尾数)。这叫做"隐含的 1",是因为浮点数格式采用了规格化表示,即浮点数的二进制表示中总是存在一个隐式的 1。
例子:将 0xC0F46A01 转换为浮点数
假设我们有一个 32 位的整数 0xC0F46A01,它的二进制表示是:
1100 0000 1111 0100 0110 1010 0000 0001
我们可以通过memcpy函数将它传给float类型变量,所以float类型存放的数据其实和整型一样,只是float还需要经过解码。
我们可以分解它为符号位、指数位和尾数位:
符号位 (S):1(表示负数)
指数位 (E):10000001(8 位,十进制为 129)
尾数位 (M):11101000110101000000001(23 位)
根据 IEEE 754 格式:
符号位 S = 1,表示负数;
指数位 E = 129,实际指数值 = ( 129 - 127 = 2 );
尾数位 M = 11101000110101000000001,表示为 ( 1/2+1/4+1/8+0/16+0/32+0/64+/0/128.......)。它的值大约是 ( 0.90625 )。
根据公式result = [(-1)^1]*[(2)^2]*(1+0.90625)=-7.625(实际上,经过精确计算,尾数 ( M ) 的值更准确地是 0.9062499999999998,这个微小的差异会导致最终结果与 -7.625 略有不同)。