32位浮点数和二进制转换(浮点数十进制与二进制之间的转换)
32位浮点数和二进制转换(浮点数十进制与二进制之间的转换)S是符号位,用来表示正负,0表示正,1表示负,只占1bit。 在IEEE-754标准中,浮点数的存储格式是这样的: 所以,最终结果就是:11 1010.101。 若采用科学计数法来表示的话,就是: 其中,指数2就如同十进制中的科学计数法中的指数10一样;10是2的二进制,101是5的二进制。
1、如何将浮点数转换成二进制呢?
简单概括起来,同样也是一句话:
整数部分依旧采用“除2取余,逆向取值”的方法;而小数部分则乘2取整,直到余下的小数为0或者满足精度要求为止,然后顺序取值(即最先得到的整数为最高位,最后得到的整数为最低位)。
比如:58.625
所以,最终结果就是:11 1010.101。
若采用科学计数法来表示的话,就是:
其中,指数2就如同十进制中的科学计数法中的指数10一样;10是2的二进制,101是5的二进制。
在IEEE-754标准中,浮点数的存储格式是这样的:
S是符号位,用来表示正负,0表示正,1表示负,只占1bit。
E是指数位,用来存储“浮点数表示成科学计数法形式时”的幂次。注意:E=常数 e,其中e就是2的幂次。
M是尾数,就是浮点数表示成科学计数法形式时小数点后面的数。
如果将上面的例子表示成这种形式的话,那就是:
其中,5=E-常数=e,M=0.11010101,S=0。
我们知道浮点数分为单精度和双精度。
若是单精度,则占4个字节,E占8位,M占23位,再加上S段,总共就是32位,刚好也是4个字节,两者是一致的。
若是双精度,则占8个字节,E占11位,M占52位,再加上S段,总共就是64位,刚好也是8个字节,这两者也是一致的。
1、那么,如果58.625是单精度浮点数,那它在内存中的二进制存储是怎么样的呢?
首先,我们先要明确一个前提:
若是单精度,那么E就占8位,取值范围就是0~255,且e=E-127,所以e的取值范围就是-127~128。
那么,接下来,我们就可以开始计算了:
显然,S=0,因为58.625是正数。
而E=e 127=5 127=132,转换成二进制就是1000 0100。
M则取小数部分,所以M=1101 0101。
所以,最终58.625在内存存储的二进制就是:
由于单精度占4个字节,所以要在不改变数值的大小的前提下将位数补齐,所以才在小数后面补0。
若是-58.625,那就只需把S改成1即可,其他位不变。
2、如果58.625是双精度浮点数,那它在内存中的二进制存储是怎么样的呢?
同样,首先,我们需要明确一个前提:
若是双精度,那么E就占11位,取值范围就是0~2047(即2048-1=2^11-1),且e=E-1023,所以e的取值范围就是-1023~1024。
接下来,我们再开始计算双精度的二进制:
显然,S=0,因为58.625是正数。
而E=e 1023=5 1023=1028=1028的二进制。
M则同样取小数部分,所以M=1101 0101。
所以,双精度的58.625在内存中的二进制存储就是:
同样,若是-58.625,则只需把S改成1即可,其他位不变。
补充:二进制浮点数如何转换成十进制浮点数?
依旧以单精度的58.625为例。
由前面可知,单精度的58.625的二进制为:
0 1000 0100 110 1010 1000 0000 0000 0000
首先,计算出指数的幂次:
明确一个前提:E=e 127
所以,E=1000 0100=132
所以,e=E-127=132-127=5
又由于S=0,所以该数值为正数。
所以,
好了,我们已经把“在内存中存储的浮点数的二进制”转换成了“我们比较好识别的浮点数的二进制”,即“能够区分出整数部分和小数部分”的浮点数的二进制。
整数部分的二进制转换成十进制,这里我们就不再赘述了。方法和普通的“十进制整数与二进制之间的转换”一样。重点和难点在于,如何将小数部分的二进制转换成十进制。那么,怎么转换呢?
首先要明确一点:小数部分是0.101
其次,将小数部分的二进制转换成十进制,其方法其实和“二进制整数转换成十进制整数”的方法是类似的,只不过,指数的幂次是负数。具体过程如下:
最后,把所计算出的十进制浮点数的整数部分和小数部分相加,就得到了最终的结果,即58.625。
但是,有一点需要注意:假设当初在将浮点数的小数部分由十进制转换成二进制时,只是计算到了“满足精度要求”为止,而并没有或者无法计算到“余下的小数为0”为止,这时,如果再用这种方法将二进制浮点数的小数部分转换成十进制,那么所计算出的十进制小数就会与实际的十进制浮点数的小数部分之间产生误差。
但如果当初在将浮点数的小数部分由十进制转换成二进制时所取的精度越大(即有效小数位数越多),那么这误差就会越小。
对于“将双精度的58.625的二进制转换成十进制”,也是同样的计算方法。这里就不再赘述了。只不过,需要注意的是E=e 1023;至于其他步骤,则都一样。
补充:二进制浮点数的小数部分转换成十进制的原理
其实,“二进制浮点数的小数部分转换成十进制”的原理,和“二进制整数转换成十进制整数”的原理类似。
我们先来回顾一下,十进制浮点数的小数部分是如何转换成二进制的。
依旧以58.625为例。转换过程如下:
然后,从上往下顺序取整,即得到0.625的二进制数为0.101。
接下来,我们反过来推导,将二进制数0.101转换回十进制数0.625。具体过程如下:
于是,最终就得到了:
显然,这个多项式中最左边项的系数1就是二进制数0.101的最低位,而最右边项的系数1就是二进制数0.101的最高位。所以,可以得到:
以上例子是一个“小数由十进制转换到二进制时可以算到‘余下的小数为0’为止”的小数。
但对于“小数由十进制转换到二进制时只能算到‘满足精度要求’为止”的小数,采用这种方法将二进制小数转换成十进制小数,则所计算出的结果会与实际的十进制小数之间产生误差。但若之前所取的精度越高(即二进制小数位数越多),则该误差就会越小。
比如:0.734就是一个“只能算到‘满足精度要求’为止”的小数。
首先,我们将0.734转换成二进制,过程如下:
0.734×2=1.468……1
0.468×2=0.936……0
0.936×2=1.872……1
0.872×2=1.744……1
0.744×2=1.488……1
0.488×2=0.976……0
……
显然,不管乘以多少次2,所得的乘积的小数部分都不可能为0,所以只能取一定精度。现假设,精度就是6位有效二进制数,那么,顺序取值而所得的0.734的二进制就是0.101110。
然后,我们再用上面的方法将二进制小数转换回十进制小数,具体过程如下:
显然,根据上面的方法所计算的结果要比实际结果0.734小,但也已经很接近0.734了。如果前面所取的精度再高一些、位数再多一些,那么所计算的结果将会更接近0.734。
这也就是为什么前面会说“有误差”的原因了。