4
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

JavaScriptで可変長数値表現を使う

Last updated at Posted at 2015-06-15

#可変長数値表現とは
可変長数値表現とは、最上位ビットをフラグをして使う数値の表現方法です。
英語ではVariable-length quantityといいます
この技術はMIDIで実装されており、時間管理に利用されています。

#数値の表現
最上位ビットをフラグに使うとは、次のようなことを意味します。

16進数 0x7F(10進数127)を、2進数で表すと、次のようになります。

//わかりやすくするために4桁で区切っています。
0111 1111

16進数0x80(10進数128)は、2進数で表すと、次のようになります。

1000 0000

一番左のビット(最上位ビット)が1になりました。
可変長数値表現では、最上位ビットに1である場合
、次のバイトにもデータがあることを示しています。
可変長数値表現で0x80を表すと

1000 0001 0000 0000

このようになります。
各バイトの最上位ビットを削除するとこうなります

000 0001 000 0000
=10000000
=0x80

単純に、各バイトの下位7ビットを連結すれば、実際の数値を取得することができます。
具体的には、ビット演算子を使えばこう書くことができます。

//ar はバイト配列とする
function decode(ar){
    var value=0;
    //最上位ビットが1ならループ
    while(ar[i]>=0x80){
         //1.最上位ビットのみ反転(例:1000 0001 => 0000 0001にする)
        var a = ar[i] ^ (1<<7);
         //2.前回の値と連結
         value = value<<7 | a;
         i++;
    }
    //最後の値を連結
    value = value <<7 | ar[i]
    return value;
}

var a = ar[i] ^ (1<<7);の部分について

ビットごとの XOR
オペランドの対応するビットがどちらか一方のみ 1 である各ビットについて 1 を返します。

これを使って、上位1ビットのみを0に反転しています。それ以外のビット(2~8ビット)に変化は起こりません。
ちなみに、1<<7 = 10000000
です。0x80と書いても同じです

前の値と連結するには、前の値を7ビット左にシフトさせ、ORします。
これにより、最上位ビットと、前の値の最下位ビット部分が重なります。
0x81 0x01 となっている可変数値表現を例にとるなら

0x81 = 10000001
0x01 = 00000001

//0x81 と 1<<7 (0x80) のXOR (最上位ビットフラグを0にする)

10000001
10000000
---------
00000001

//0x01と上記の連結
//0000001を7ビット左にシフト
0000001 << 7 = 10000000

//0x01とOR
10000000
00000001
--------
10000001

=0x80

こんな感じです。わかりましたか?

なお、可変長数値表現に変換したい場合は、下記のようにすれば可能です


function convert(val){ 
  var buffer = [];
  buffer.push((val & 0x7F));
  val = (val >> 7)
  while (val > 0) {
    buffer.push(0x80 + (val & 0x7f))
    val = (val >> 7)
  }
   array2hex(buffer.reverse());
 

    function array2hex(ar) {
      for (var i=0;i<ar.length;i++) {
        ar[i] = (ar[i].toString(16) == 0) ? "00" : ar[i].toString(16);
      } 
       return "0x" + ar.join('');
   }
  }
}

上記コードは下記より引用しました
https://gist.github.com/silentrob/440159

4
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?