「JavaScript/ビット演算」の版間の差分

削除された内容 追加された内容
Ajedony (トーク | 投稿記録)
M カテゴリ追加
10 行
JavaScriptはビット(二値)演算をサポートしている。
 
* & ビットごとのAND(論理積)
* | ビットごとのOR(論理和)
* ^ ビットごとの排他的 OR(排他的論理和)
* << 左シフト
* >> 右シフト
30 行
 
=== 2進法の表記法 ===
 
回路構成を単純にするため、内部的に2進法を用いており通常2進法で計算できるものはこちらで計算したほうが高速であるため
こちらを利用する。
 
10進法 1 2 3 4 5 6 7 8 9 10
 
2進法 1 10 11 100 101 110 111 1000 1001 1010
 
3進法 1 2 10 11 12 20 21 22 100 101 102
 
4進法 1 2 3 10 11 12 13 20 21 22
 
* [[w:二進記数法]]
 
=== 補数 ===
 
補数とは2進法で、負の値を表現するための非常に巧みな方法であるが、アセンブラでのプログラム等非常に低レベルでのプログラミング以外で実際に使用される事は稀である。
簡単のため、この項の解説はあえて省略をする。
 
* [[w:補数]]
 
=== ビットシフト ===
ビットシフトとは、2進数のビットをそのまま、右側、または左側にずらず事を言う。空いたビットには0が埋められる。
これは実質、2の倍数の乗算、余算に等しい。ただし、こちらの方が高速に動作する。
 
<nowiki>
1 << 2; // 1が2ビット左シフトするため、2進数で「100」つまり4が返る
13 >> 2; // 「1101」から右シフトして2進数で「11」、つまり3が返る </nowiki>
 
JavaScriptでは正負の記号は保存される。
しかし、符号なし右シフト演算子を使った場合にはこの結果は異なる。
<nowiki>
-10>>1; // -5
-10>>>1; // 2147483643が返る </nowiki>
これは、先頭にある正負の記号を表すビットもシフトさせるためである。
 
 
=== 論理演算 ===
 
実際には、ビット積ビットマスク使用する事が多いでこちら解説の重点を置使う
 
論理積を例に挙げる。
論理積の結果を表に表すと次の様になっている。
 
論理積
1 1 1
1 0 0
0 1 0
0 0 1
 
論理積の演算子は"&"であるから、実際の演算を行うと次の様になる。
<nowiki>
1 & 1; // 1が返る
1 & 0; // 0が返る
0 & 1; // 0が返る
0 & 0; // 0が返る </nowiki>
 
同じように、論理和、排他的論理和の計算結果を挙げると次の様になっている。
<nowiki>
// 論理和の演算
1 | 1; // 1が返る
1 | 0; // 1が返る
0 | 1; // 1が返る
0 | 0; // 0が返る
 
// 排他的論理和の演算
1 ^ 1; // 0が返る
1 ^ 0; // 1が返る
0 ^ 1; // 0が返る
0 ^ 0; // 1が返る </nowiki>
 
これらの演算はビットごとに行われるため、通常の四則演算とは違った考え方で結果を捉える必要がある。
例として10進数で7を挙げる、これを2進数に直すと、「111」となる。
同じように2も2進数では「10」と表記されるため、このビット積「7&2」は次の様に、ビットごとの計算が行われるため次の様になる
 
1 1 1
 
0 1 0
 
1 0 1
<nowiki>
7&2; // 2進数では111 & 010 、この結果は2進数で「101」なので「5」である </nowiki>
 
この性質を利用すればビット積で末尾1ビットを残すことで、奇数、偶数の判別が可能である
<nowiki>
num&1 // 1なら奇数、0なら偶数 </nowiki>
 
0となった値を1にするにはビット和を利用する。
 
<nowiki>
10 | 13; // 2進数では、1010 | 1101であるから、結果は「1111」、つまり15が返る</nowiki>
 
(2進法よりも簡潔な記述を行うため、実際のコードで16進法で記述を行う)
 
この仕掛けを利用すれば、一つの数字データに複数のデータを格納できる事に気づく
例えば、コンピュータ内部で色を扱う場合の例で、数値型データの中から、32ビットの数値を8ビットごとに区切ってそれぞれ、透明度、赤、緑、青を格納している。
(これをARGB系と呼んでいる)
取り出す場合には、次の様にコードを記述する。色を一つの数字型にまとめて格納することが出来る
 
<nowiki>
/**
* ビットデータを、色を含んだ構造体に変更する
*/
function getColor( color ){
return {
a:(color & 0xff000000)>>24,
r:(color & 0x ff0000)>>16,
g:(color & 0xff00)>>8,
b:color & 0xff
};
}
getColor( color ).r; // 赤を取り出し </nowiki>
 
* [[w:ブール代数]]
* [[w:ビット演算]]
 
実際にはビット演算には他にも数多くのテクニックが存在するが、今回のその解説は省略した。
逆にOR演算子はビットをオンにするのに使う
JavaScriptでのプログラミングでは、スクリプトの評価の方が処理時間をとっているためC言語などでの高速化手法としては使われない
そのため、InternetExplolerでActiveXオブジェクトとのデータのやりとりなど、他の言語環境とのデータのやり取りに使われることもあるが、実際にこれらの演算手法を使う機会は他の言語より少ない。
基本的には、配列などの他の方法を使うよりこちらの方が鮮やかに記述できる場合に利用すべきである。
 
=== 余談:世界最初のコンピューターは二進法でない!? ===
* [[Wikipedia:ブール代数]]
世界最初のコンピューターとして現在知られているENIAC(エニアック)は、10進数での計算方法を行っています。
* [[Wikipedia:ビット演算]]
つまりは、計算して出てきた結果を電圧ごとに10分割して、これ以上は1これ以上は2...と区切って計算をしています。
しかし、現在の計算機では内部的には、電圧が一定以上か、それ以下かでON/OFFを判別して計算を行っています。
この変化は実際にかなり早い時期におこっており、1946年のENIACの登場の後に、2進数での設計の方が回路構成が単純になるという論文が登場しており、後継の1951年のEDVAC(エドバック)では既に2進数での計算に移っています。
 
*[[Categoryw:JavaScriptENIAC]]