参考
http://blog.sina.com.cn/s/blog_7f0562030102x04i.html一个浮点数由2部分组成:底数m 和 指数e。 ±mantissa × 2exponent (注意,公式中的mantissa 和 exponent使用二进制表示)浮点数据就是按下表的格式存储在4个字节中: Address+0 Address+1 Address+2 Address+3 Contents: SEEE EEEE EMMM MMMM MMMM MMMM MMMM MMMM
S: 表示浮点数正负,1为负数,0为正数
E: 指数加上127后的值的二进制数
M: 24-bit的底数(只存储23-bit,最高位始终为 1)
主意:这里有个特例,浮点数 为0时,指数和底数都为0,但此前的公式不成立。因为2的0次方为1,所以,0是个特例。
以上面的数据为例:
这四个字节在内存中为:
16进制:45 33 83 76
2进制:0100 0101 0011 0011 1000 0011 0111 0110
S为0,表示正数。E为1000 1010,即138,减去127为11。M为1.011 0011 1000 0011 0111 0110,右移11位为1011 0011 1000. 0011 0111 0110。转换为10进制为2872.21630859375。
代码:
$hex_two = base_convert($hex,16,2);
$hex_all = "";
if(strlen($hex_two)%2==0){
$hex_all = $hex_two;
}else{
$hex_all = "0".$hex_two;
}
$count_hex = strlen($hex_all)-1;
$hex_py = substr($hex_all,1,8); //第一位是正负,前八位偏移量
$py_sjz = bindec($hex_py); //转十进制
$py = $py_sjz - 127; //补位
$zs_py_e = substr($hex_all,9,$py);
$zs_e = "1".$zs_py_e; //整数部分二进制
$zs_s = bindec($zs_e);
$xs_jj = 9+$py; //小数部分
$xs_py_e = substr($hex_all,$xs_jj,$count_hex);
$xs_s = 0;
for ($i=1; $i < strlen($xs_py_e); $i++) {
$xs_s = $xs_s+$xs_py_e[$i]*pow(2,-$i);
}
$xs_s = $xs_s/2;
$count_xs = strlen($xs_s)-1;
$xs_s = substr($xs_s,2,$count_xs);
$return = $zs_s.".".$xs_s;
$return_value = round($return,6);
return $return_value;