サイトトップ

Director Flash 書籍 業務内容 プロフィール

HTML5テクニカルノート

2進数・16進数とビット演算

ID: FN1509001 Technique: HTML5 and JavaScript

2進数や16進数の表し方と、2進数を基礎としたビット演算について簡単にご紹介します。

Word 001■ビット
ビット(bit)は、コンピュータが扱う最小の単位で、2値つまりふたつの状態のうちのひとつを示します。2値を0か1とすれば、2進数の1桁が1ビットになります(Wikipedia「ビット」参照)。ビット演算は、2進数をビットつまり1桁ごとに処理します。


01 2進数

2進数は0と1のみで数を表します。10進数が9に1を加えた10で繰り上がるのに対して、2進数は1に1を足した2で桁が上ります。したがって、2進数の10(= 1 + 1)は、10進数の2になる訳です。同じように、2進数の100と1000は、それぞれ10進数の4と8になります。ですからたとえば、2進数の1010は、つぎのように10進数の10と計算できます。

1×8 + 0×4 + 1×2 + 0×1 = 10

8は23、4は22、2は21、そして1は20ですから、上の式はつぎのように書直すこともできます。

1×23 + 0×22 + 1×21 + 0×20 = 10

一般に、2進数で表した数の各桁の小さい方から順に、n1、n2、...、nkとすると、これを10進数にするのはつぎの式になります。

nk×2k-1 + … + n2×21 + n1×20

また、10進数についても、各桁の数を小さい方から順に、n1、n2、...、nkとすれば、べき乗(累乗)される数を10に替えて、つぎのように示すことができます。

nk×10k-1 + … +n2×101 + n1×100

この考え方はさらに一般化できますので、i進数(iは正の整数)はつぎの式で表されます。

nk×ik-1 + … + n2×i1 + n1×i0

02 複数のフラグをひとつの整数で表す

2進数を使うと、複数の2値のフラグをひとつの数値で効率的に表すことができます。

たとえば、2値のフラグとなるBoolean型の変数が4つあったとします。仮に、変数をa、b、c、dとし、それぞれの値がtruefalsetruefalseだったとしましょう。このとき、4桁の2進数を考え、頭から変数a、b、c、dを当てはめて、trueを1、falseを0とすれば、4つのフラグの値は以下のように2進数1010で表されます。したがって、10進数の10でフラグaとcがオン(true)であることを示せます。

フラグの変数 a b c d
変数の値 true false true false
2進数の桁番号 4 3 2 1
桁に乗じる値 23 22 21 20
2進数の桁の値 1 0 1 0

03 ビットごとの論理演算子

ビットごとの論理演算子は、2進数を各桁ごとに演算し、他の桁には影響を与えません。つまり、繰り上がりや繰り下がりがなく、結果は0か1のいずれかになります。オペランド(被演算子)も0か1ですので、4とおりの組合わせが考えられ、ビットごとの論理和演算子|の演算結果は下表001のとおりです。

表001■ビットごとの論理和演算子|の演算結果
オペランド 0 1
0 0 1
1 1 1

「論理和」という名称は、条件を指定するときの論理和演算子||にも使われていました。この演算子は、オペランドがブール(論理)値の場合、いずれか一方がtrueであればtrueを返します。ビットごとの論理和演算子|も、同じように、オペランドのいずれか一方が1であれば1を返します。したがって、2進数で表記した1010 | 1100の演算結果は、2進数の1110となります。

Tips 001■2進数と10進数の変換
本文の「1010 | 1100」という演算は、もちろんそのままスクリプトでは試せません。数値が10進数として扱われてしまうからです。したがって、2進数を一旦10進数に直して、論理和演算子|を用いなければなりません。

2進数を10進数に数値として変換するには、本文に述べた2の累乗を各桁に掛合わせる式を使う必要があります。しかし、文字列で表した2進数は、perseInt()関数で簡単に10進数に変えられます。

perseInt()関数は、つぎの構文で用います。「基数」というのは、何進数として解析・変換するのかという正の整数です。

perseInt(文字列で示した整数, 数値に変換するための基数)

したがって、文字列で表した2進数の"1010"と"1100"を10進数に変換するには、perseInt()関数をつぎのように使います。それぞれの値は、10進数の10と12になります。

var a_str = "1010";
var b_str = "1100";
var a = parseInt(a_str, 2);
var b = parseInt(b_str, 2);
console.log(a, b);   // 10 12

論理和演算子|はオペランド(被演算子)に10進数を指定しても、2進数に直して演算し、結果をまた10進数で返します。10進数の数値を、perseInt()関数とは逆に、2進数の文字列に変換したいときは、Number.toString()メソッドに引数として基数を渡します(デフォルトは10)。

var answer = a | b;
console.log(answer);   // 出力: 14
var answer_str = answer.toString(2);
console.log(answer_str);   // 1110

ビットごとの論理演算子には、ほかにビットごとの論理積演算子&ビットごとの排他的論理和演算子^があります。ビットごとの論理積演算子&は、条件の論理積演算子&&と同じ考え方で、オペランドがともに1のときのみ1を返します(他の場合は0)。ビットごとの排他的論理和演算子^は、オペランドの一方のみが1のとき1を返し、それ以外は0を返します。下表002と003に、その演算結果を示します。

表002■ビットごとの論理積演算子&の演算結果
オペランド 0 1
0 0 0
1 0 1

表003■ビットごとの排他的論理和演算子^の演算結果
オペランド 0 1
0 0 1
1 1 0

04 16進数とRGBカラー値

16進数もコンピュータではよく使われます。もちろん、16進数も前掲の式にしたがって、つぎのように表されます。

nk×16k-1 + … + n2×161 + n1×160

しかし、私たちが使う算用数字には、0から9までしかありません。そこで、それ以降はAからFまでのアルファベットで示されます。もっとも、16進数表記は、Webではよく見かけます。なじみが深いのはRGBカラー値でしょう。このRGBカラーも、赤(R)緑(G)青(B)それぞれに別の桁を割振ることにより、ひとつの値で3つのカラー成分値を表します(図001)。

図001■RGBカラー値
図001
6桁の16進数で、RGBそれぞれの成分値をひとつの数値で表す。

JavaScriptでは、16進数表記で整数を示すことができます。その場合、数値の前に0xを記述します。たとえば、ブルーの#0000FFは、つぎのように数値として表します。

var colorInt = 0x0000FF;
console.log(colorInt);   // 255

それぞれのカラーが16進数ふた桁を使うのは、カラー成分値が0から255までの256階調であることにもとづきます。つまり、16進数で表しているとはいえ、実質256進数です。そこで、たとえば各カラー成分値が0から255までの整数で3つの変数に代入されていた場合、3つの成分を合わせたカラー値はつぎの式で求められます。

カラー値 = R成分値×2562 + G成分値×2561 + B成分値×2560

スクリプトでは、たとえば以下のように試すことができます。

var r = 0xFF;
var g = 0x33;
var b = 0x99;
var colorInt = r * 256 * 256 + g * 256 + b;
console.log(colorInt, colorInt.toString(16));   // 16724889 "ff3399"

ご参考までに、RGBのカラー成分を3つの引数としてカラー値の整数が得られる関数(getColorInt())を以下のコード001に示します。

console.log(getColorInt(0xFF, 0x33, 0x99));   // 16724889
コード001■RGBカラー成分値からカラー整数値を得る関数
  1. function getColorInt(r, g, b) {
  2.   var colorInt = r * 256 * 256 + g * 256 + b;
  3.   return colorInt
  4. }

05 カラー値とビット演算

16進数がコンピュータでよく使われるのは、値を2進数4桁で扱うことができるからです。つまり、16進数の0からFは、2進数の0から1111までの値になります。16進数で1桁繰り上がるつまり16を掛合わせるという処理は、2進数を左に4桁ずらすのと同じです。また、16進数で2桁繰り上げるのは256を掛ける演算で、2進数では8桁動かすことになります(図002)。

図002■256を掛ける処理は2進数で8桁左にずらすのと同じ
図002
16進数で2桁繰り上げるのは、256を掛合わせる処理。2進数で8桁左にずらすのとおなじ結果になる。

JavaScriptでは、この2進数で桁をずらすというビット演算ができます。左に桁をずらすには、ビットの左シフト演算子<<を使います。ビットの左シフト演算子<<の左側オペランドには2進数としてビット演算する対象の式、右側オペランドには左に動かすビット(桁)数を指定します。

すると、前掲コード001「RGBカラー成分値からカラー整数値を得る関数」(getColorInt())はつぎのコード002のように書き替えられます。もちろん、どちらの関数でも同じ結果が得られます。ただ、2進数をビットごとに扱う演算子は、繰り上がりや繰り下がりがなく、コンピュータのデジタル(1/0)のロジックにより近いため処理効率で勝るところがあります。

コード002■RGBカラー成分値からカラー整数値をビット演算で求める関数
  1. function getColorInt(r, g, b) {
  2.   var colorInt = r << 16 | g << 8 | b;
  3.   return colorInt
  4. }

illustration
16進数の2桁繰り上がりは、2進数で8桁左にずらせばよい。

逆に、RGBカラー値から各成分値を取出すには、ビットの右シフト演算子>>とビットごとの論理積演算子&を使います。以下のスクリプトの処理内容は、ビット演算の練習問題として考えていただくのにちょうどよいでしょう。理解しにくいときは、各値をそれぞれ2進数に変換(toString(2))して確かめ、演算の結果と比べてみることです。

var colorInt = 0xFF3399;
var b = colorInt & 0xFF;
var g = (colorInt >> 8) & 0xFF;
var r = (colorInt >> 16) & 0xFF;
console.log(r.toString(16), g.toString(16), b.toString(16));   // ff 33 99

前掲コード002とは逆に、カラーの整数値からRGB成分値を求める関数(getRgbComponents())は以下のコード003のように定めました。RGBの3成分値は、Objectインスタンス(rgbComponents)のプロパティとして納められます。

var rgbComponents = getRgbComponents(0xFF3399);
console.log(rgbComponents.r.toString(16), rgbComponents.g.toString(16), rgbComponents.b.toString(16));   // ff 33 99

コード003■カラー整数値からRGBカラー成分値をビット演算で求める関数
  1. function getRgbComponents(colorInt) {
  2.   var rgbComponents = {};
  3.   rgbComponents.b = colorInt & 0xFF;
  4.   rgbComponents.g = (colorInt >> 8) & 0xFF;
  5.   rgbComponents.r = (colorInt >> 16) & 0xFF;
  6.   return rgbComponents
  7. }


作成者: 野中文雄
作成日: 2015年9月26日


Copyright © 2001-2015 Fumio Nonaka.  All rights reserved.