FrontPage

可変長数値表現を実装する

可変長数値表現とは、あらかじめ大きさの分からない数値を、少ないバイト数で表現しようとする工夫である。
オクテットのうち最上位ビットを、次のオクテットが続くかの判定に用い、残りの7ビットを数値表現に使う。
したがって、127以下の数値が頻繁に登場するようなデータをファイルに出力する場合などに、大きな効果が期待できる。
有名なのは、Standard MIDI Fileのデルタ値表現である。

今回は、INT型の数値を可変長数値表現で表すコードを載せてみます。

VLNE.png

C++による可変長数値表現のテスト

#include        <stdio.h>                                       //  標準入出力                                    //
                                                                //                                                //
int numInBytes( unsigned char* vd_bytes, int vd_data );         //  可変長数値表現を行う関数                      //
                                                                //                                                //
/* VLNE Test **************************************************//*  可変長数値表現のテスト                        */
int main( void )                                                //                                                //
{                                                               //                                                //
    int data = 0;                                               //  元となるデータ                                //
    int byteCnt = 0;                                            //  消費したバイト数の受取り用                    //
    int cnt = 0;                                                //  ループカウンタ                                //
    unsigned char bytes[4] = { 0, 0, 0, 0 };                    //  最大で4バイトの消費を見込む                   //
                                                                //                                                //
    for( ; ; )                                                  //  無限ループ                                    //
    {                                                           //                                                //
        printf( "input >" );                                    //  画面表示                                      //
        scanf( "%d", &data );                                   //  元となるデータの取得                          //
                                                                //                                                //
        byteCnt = numInBytes( bytes, data );                    //  可変長数値表現を依頼                          //
                                                                //                                                //
        for( ; byteCnt > cnt; cnt++ )                           //  消費したバイト数分繰り返す                    //
        {                                                       //                                                //
            printf( "%#2x " , bytes[cnt] );                     //  画面表示                                      //
        }                                                       //                                                //
                                                                //                                                //
        break;                                                  //  ループを抜ける                                //
    }                                                           //                                                //
                                                                //                                                //
    return( 0 );                                                //  処理終了                                      //
}                                                               //                                                //
//*VLNE Test **************************************************//*  可変長数値表現のテスト                        */
/* Variable Length Numeric Expression *************************//*  可変長数値表現を行う関数                      */
int numInBytes( unsigned char* vd_bytes, int vd_data )          //                                                //
{                                                               //                                                //
    int rtnNum = 0;                                             //  消費したバイト数を返すリターンコード          //
                                                                //                                                //
    if( 0x7F >= vd_data )                                       //  デルタ値が1バイトで表せるか                   //
    {                                                           //  デルタ値が1バイトで表せる場合                 //
        vd_bytes[0] = (char)vd_data;                            //  1バイト目にそのまま格納                       //
        rtnNum = 1;                                             //  消費したバイト数をリターンに設定              ///
    }                                                           //                                                //
    else if( 0x3FFF >= vd_data )                                //  デルタ値が2バイトで表せるか                   //
    {                                                           //  デルタ値が2バイトで表せる場合                 //
        vd_bytes[0] = 0x80 | ((vd_data & 0x3F80) >> 7);         //  1バイト目を編集                               //
        vd_bytes[1] = 0x7F & vd_data;                           //  2バイト目を編集                               //
        rtnNum = 2;                                             //  消費したバイト数をリターンに設定              //
    }                                                           //                                                //
    else if( 0x1FFFFF >= vd_data )                              //  デルタ値が3バイトで表せるか                   //
    {                                                           //  デルタ値が3バイトで表せる場合                 //
        vd_bytes[0] = 0x80 | ((vd_data & 0x1FC000) >> 14);      //  1バイト目を編集                               //
        vd_bytes[1] = 0x80 | ((vd_data & 0x3F80) >> 7);         //  2バイト目を編集                               //
        vd_bytes[2] = 0x7F & vd_data;                           //  3バイト目を編集                               //
        rtnNum = 3;                                             //  消費したバイト数をリターンに設定              //
    }                                                           //                                                //
    else if( 0x0FFFFFFF >= vd_data )                            //  デルタ値が4バイトで表せるか                   ///
    {                                                           //  デルタ値が4バイトで表せる場合                 ///
        vd_bytes[0] = 0x80 | ((vd_data & 0x0FE00000) >> 21);    //  1バイト目を編集                               // 
        vd_bytes[1] = 0x80 | ((vd_data & 0x1FC000) >> 14);      //  2バイト目を編集                               // 
        vd_bytes[2] = 0x80 | ((vd_data & 0x3F80) >> 7);         //  3バイト目を編集                               // 
        vd_bytes[3] = 0x7F & vd_data;                           //  4バイト目を編集                               // 
        rtnNum = 4;                                             //  消費したバイト数をリターンに設定              ///
    }                                                           //                                                //
                                                                //                                                //
    return( rtnNum );                                           //  消費したバイト数を返して終了                  //
}                                                               //                                                //
//*Variable Length Numeric Expression *************************//*  可変長数値表現を行う関数                      */

表示結果:

input >16384
0x81 0x80  0

修正履歴


課題

  • 備考

参考ページ

Wikipedia


トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2010-02-08 (月) 02:08:25 (5185d)