php接收终端数据需要涉及到解析转码函数

 
<?
//数据为integer类型
$bytes=array(
0x55,0xAA,0x01,0x82,0x00,0x00,0x00,0x00,
0x44,0x00,0x4D,0xED,0x43,0x4F,0x2D,0x48,
0x45,0x41,0x4C,0x54,0x48,0x38,0x36,0x36,
0x37,0x36,0x32,0x30,0x32,0x31,0x32,0x33,
0x35,0x34,0x33,0x35,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x8E,0x01,0x00,0x00,
0xD1,0x07,0x01,0x01,0x14,0x10,0x21,0x00,
0x66,0x66,0xD6,0x40,0x02,0x00,0x00,0x00,
0x00,0x00,0x00,0x00
);
function check_data($bytes){
    if(count($bytes)<12) return false;//头部长度判断
    $new_H_CHK=~($bytes[0]+$bytes[1]+$bytes[2]+$bytes[3]+$bytes[4]+$bytes[5]+$bytes[6]+$bytes[7]+$bytes[8]+$bytes[9]+$bytes[11]);
    $new_H_CHK=bindec(substr(sprintf("%b",$new_H_CHK),-8))+1;
    $old_H_CHK=$bytes[10];
    if($new_H_CHK!==$old_H_CHK) return false;//新生成的new_H_CHK跟数据中的H_CHK对比,如果数据是一样则会相等
    $validate_header=$bytes[0]+$bytes[1]+$bytes[2]+$bytes[3]+$bytes[4]+$bytes[5]+$bytes[6]+$bytes[7]+$bytes[8]+$bytes[9]+$bytes[10]+$bytes[11];
    $validate_header=bindec(substr(sprintf("%b",$validate_header),-8));
    if($validate_header!==0) return false;//根据公式再次完整校验头部
    $datalen=bindec(substr(sprintf("%b",$bytes[9]),-8).substr(sprintf("%b",$bytes[8]),-8));//获取包长度
    $bytelen=count($bytes);
    if($datalen!=$bytelen) return false;//包长度校验
    $sum_data=NULL;
    for($i=12;$i<$bytelen;$i++){
        $sum_data+=$bytes[$i];//计算数据和值
    }
    $new_D_CHK=bindec(substr(sprintf("%b",~$sum_data),-8))+1;
    $old_D_CHK=$bytes[11];
    if($new_D_CHK!==$old_D_CHK) return false;//校验新生成的new_D_CHK和old_D_CHK,如果数据是一样则会相等
    $validate_data=bindec(substr(sprintf("%b",$old_D_CHK+$sum_data),-8));
    if($validate_data!==0) return false;//根据公式再次校验数据完整性
    $a=0x66;$b=0x66;$c=0xD6;$d=0x40;
    echo get_float32($d,$c,$b,$a);
    return true;
}
//32位的二进制浮点数转回十进制的php浮点数
function get_float32($a,$b,$c,$d){
    $float32=sprintf("%08b%08b%08b%08b",$a,$b,$c,$d);
    $S=substr($float32,0,1);//符号位
    $E=substr($float32,1,8);//指数位
    $E=bindec($E)-127;//减去中间数,获取真实的指数位,有可能是0减去127
    $M=substr($float32,9);//有效数字,被减去1
    $floatbin="";
    if($E>0){
        if($E!=128){//防止指数位全1
            $floatbin="1".substr($M,0,$E)."_".substr($M,$E);
        }
    }else if($E<0){
        if(abs($E)==1){
            $floatbin=str_pad("",1,"0")."_1".$M;
        }else if($E!=-127){//防止指数位全0情况,即为0值
            $floatbin="0_".str_pad("",abs($E)-1,"0")."1".$M;
        }
    }else if($E==0){
        $floatbin="1_".$M;
    }
    $intpart=$decpart="";
    if(!empty($floatbin)){
        list($intpart,$decpart)=explode("_",$floatbin);
    }
    $val=0;
    for($i=1;$i<=strlen($intpart);$i++){
        $val+=(intval($intpart[$i-1]))*pow(2,strlen($intpart)-$i);//二进制转回整数
    }
    for($i=1;$i<=strlen($decpart);$i++){
        $val+=(intval($decpart[$i-1]))*pow(2,0-$i);//二进制转回小数部分
    }
    $val=$S==1?0-$val:$val;//符号数判断
    return $val;
}
var_dump(check_data($bytes));
?>

calc十进制小数转二进制

Windows自带的计算器可以方便地把十进制的整数转换成二进制的整数,但是十进制的小数则无法直接转换成二进制的小数。
今天,我发现了一个快速的解决办法!
一个十进制小数可以表示成“X.Y”的形式,“X”是整数部分,“Y”是纯小数部分,要分别进行转换,最后合在一起。
整数部分“X”的转换成二进制可以直接利用Windows的计算器,非常简单,不说了。
对纯小数部分“Y”的转换,要提前设定转换精度,比如精确到小数点后16位。别理解错了,对于二进制的小数点后16位在精度上仅相当于十进制小数点后的5位,并非十分高!
将“0.Y”乘以2的16次方,即“0.Y×65536”,结果可能会有小数部分,将小数部分四舍五入到个位,得到一个没有小数部分的纯整数,称作“Z”。
利用Windows计算器将“Z”转换成二进制,若结果不足16位,则在最前面补0,补够16位。这就是小数部分“Y”对应的二进制了。
现在将“X”和“Y”对应的二进制数码合在一起(中间当然要有小数点),就是最终结果了!
举个实例:把十进制纯小数“0.123”转换成二进制小数。
0.123×65536=8060.928
四舍五入后得到“8061”,转换成二进制为“1111101111101”,只有13位,前面需要补3个“0”,得到“0001111101111101”。因此结果是
0.123=(0.0001111101111101)2=(0.1F7D)16

 

浮点数二进制表示

http://blog.csdn.net/richerg85/article/details/20456969

原文地址:https://www.cnblogs.com/boodoog/p/6047591.html