zoukankan      html  css  js  c++  java
  • varint算法——本质上是牺牲最高位作为标识数据结束位,达到变长编码,说白了就是贪心的分割位

    varint算法,摘自:http://blog.csdn.net/liaoquesg/article/details/50897327

    最近在看《大规模WEB服务开发技术》这本书中。书中提到“可变长字节码算法”的压缩数据的算法,以达到压缩数据,减少磁盘IO。 
    可变长字节码算法: 
    任意一个字节的最高位(下标7)均只作为标志位,而且根据字节所在位置需要乘以128的相应幂次;(我觉得这个算法只能用作自然数的压缩)

    这是他的伪代码 
    这里写图片描述

    仔细研究后,我翻译成PHP版的:

        <?php
        function codeNumber($n){
            $bytes = [];
            while (true){
                array_unshift($bytes, bcmod($n, 128));
                if($n < 128){
                    break;
                }else{
                    $n = intval($n/128);
                }
            }
            $bytes[count($bytes) - 1] += 128;
            return $bytes;
        }
    
        function encode($numbers){
            $bytestream = [];
            foreach ($numbers as $n){
                $bytestream = array_merge($bytestream, codeNumber($n));
            }
            return $bytestream;
        }
    
        function decode($bytestream){
            $numbers = [];
            $n = 0;
            for ($i = 0; $i < count($bytestream); $i++){
                if($bytestream[$i] < 128){
                    $n = 128 * $n + $bytestream[$i];
                }else{
                    $n = 128 * $n + ($bytestream[$i] - 128);
                    array_push($numbers, $n);
                    $n = 0;
                }
            }
            return $numbers;
        }
        $a = encode([5, 130, 288]);
        var_dump($a);
        var_dump(decode($a));
    
    打印出来的内容是:
    array(5) { [0]=> int(133) [1]=> string(1) "1" [2]=> int(130) [3]=> string(1) "2" [4]=> int(160) }
    array(3) { [0]=> int(5) [1]=> int(130) [2]=> int(288) }
    
        //写二进制
        $h = fopen('ejz3.txt', 'wb');
        foreach ($a as $k => $v)
        {
          $str3 =  pack('H*', sprintf("%02x", $v));
          fwrite($h,  $str3);
        }
        fclose($h);
    
        //读二进制
        $str2 = file_get_contents('ejz3.txt');
        $str2 = unpack("H*", $str2);
        $value = str_split($str2[1], 2);
        foreach ($value as $k => $v)
        {
          $value[$k] = base_convert($v, 16, 10);
        }
     
  • 相关阅读:
    Redis系列一
    浅谈Java开发三层架构
    plsql乱码问题
    eclipse工作空间的常用设置
    《经典面试系列》- 索引
    《数据库优化》- 存储过程
    遍历Map的四种方式(Java)
    调用微信js sdk
    根据多个成对的cron表达式生成的时间段,合并
    关于Map集合注意事项
  • 原文地址:https://www.cnblogs.com/bonelee/p/6655223.html
Copyright © 2011-2022 走看看