原文使用了C语言演示IEEE标准,但该标准适用于MySQL。
在C语言中,浮点型变量(也就是带小数位的实数)在内存中的存储方式遵循IEEE标准。
首先来看单精度浮点型float。float占用4字节空间,也就是32位。从左向右数,第1位是符号位(0代表正数,1代表负数),接着是8位指数位,剩下的23位是数据位。如下所示
S EEEEEEEE DDDDDDDDDDDDDDDDDDDDDDD
由于采用了科学计数法,所有的23位D位(数据位)全部用来记录小数点右边的数据,因为小数点左边只有1位且它肯定是1(二进制)。
以3.5为例,它的二进制形式是 11.1,转换为科学计数法是 1.11E1。可以知道 S位(符号位 )应填入正(0),E位(指数位)为应填入1,D位(数据位)应填入11。
PS:选择3.5的原因是它可以正好被精确地转换成二进制数。大多数的小数是不能被精确地转换的,这涉及到十进制小数转换二进制的精度问题。如3.6会是11.100110011001100(1100…)这种无限循环, 转换成IEEE标准的小尾则是 66 66 66 40。为了方便和精确,本文选择了3.5和-10.625这两个可以被精确转换的数。
需要注意的是,E位的编码形式并非常用的补码形式(正数是它本身,负数符号位变1数据取反加一),而是把E位的8位能代表的数据空间(0-255)左右分为两半,以127为中点,代表0。如果指数为是1,则E位是128;如果指数位是2,则E位是129;如果指数位是-1,则E位是126,以此类推。
回到3.5的例子,我们可以得到E位实际上应该是128,也就是10000000。D位从左向右开始填,没有的则为0。 所以,3.5的浮点表达为
0 10000000 11000000000000000000000
整理为4位一组,则是
0100 0000 0110 0000 0000 0000 0000 0000
4 0 6 0 0 0 0 0
可以推测,以小尾方式存储在内存中的3.5,它的形式应该是 0000 6040。用如下的示例程序结合WinHex来验证。