Next: , Previous: , Up: Numbers   [Contents][Index]


3.8 整数のビット演算

コンピューターの中では、整数はビット(bit: 0か1の数字)のシーケンスである、2進数で表されます。ビット演算は、そのようなシーケンスの中の個々のビットに作用します。たとえば、シフト(shifting)はシーケンス全体を1つ以上左または右に移動して、“移動された”のと同じパターンを再生します。

Emacs Lispのビット演算は整数だけに適用されます。

Function: lsh integer1 count

lshlogical shiftの略で、integer1のビットを左にcount個シフトする。countが負なら右にシフトし、シフトにより空きになったビットには0がセットされる。countが負ならlshは左端(最上位)に0をシフトするので、integer1が負の場合でも正の結果が生成される。これと対照的なのが以下で説明するashである。

以下はlshでビットパターンの位置を1つ左にシフトする例である。ここでは下位8ビットの2進パターンだけを表示しており、残りのビットはすべて0である。

(lsh 5 1)
     ⇒ 10
;; 10進の5が10進の10になる
00000101 ⇒ 00001010

(lsh 7 1)
     ⇒ 14
;; 10進の7は10進の14になる
00000111 ⇒ 00001110

この例が示すように、ビットパターンを左に1シフトすると、生成される数は元の数の2倍になる。

ビットパターンを左に2シフトすると、以下の結果が生成される(8ビット2進数):

(lsh 3 2)
     ⇒ 12
;; 10進の3が10進の12になる
00000011 ⇒ 00001100

一方、右に1シフトすると以下のようになる:

(lsh 6 -1)
     ⇒ 3
;; 10進の6は10進の3になる
00000110 ⇒ 00000011

(lsh 5 -1)
     ⇒ 2
;; 10進の5は10進の2になる
00000101 ⇒ 00000010

例で明らかなように右に1シフトすることにより、正の整数の値が2で除され下方に丸められる。

関数lshは他のEmacs Lisp算術関数と同様、オーバーフローをチェックしないので、左にシフトすることにより上位ビットが捨てられ、その数の符号が変化するかもしれない。たとえば30ビットの実装では、536,870,911を左にシフトすると-2が生成されます。

(lsh 536870911 1)          ; 左シフト
     ⇒ -2

2進ではこの引数は以下のようになる:

;; 10進の536,870,911
0111...111111 (全部で30ビット)

これを左にシフトすると以下のようになる:

;; 10進の-2
1111...111110 (全部で30ビット)
Function: ash integer1 count

ash (算術シフト(arithmetic shift))は、integer1の中のビット位置を左にcountシフトする。countが負なら右にシフトする。

ashlshと同じ結果を与えるが、例外はinteger1countがいずれも負の場合である。この場合、lshは左にできる空きビットに0、ashは1を置く。

したがってashでビットパターンの位置を右に1シフトすると以下のようになる:

(ash -6 -1) ⇒ -3
;; 10進の-6は10進の-3になる
1111...111010 (30 bits total)
     ⇒
1111...111101 (30 bits total)

対照的に、lshでビットパターンの位置を1右にシフトすると以下のようになる:

(lsh -6 -1) ⇒ 536870909
;; 10進の-6は10進の536,870,909になる
1111...111010 (30 bits total)
     ⇒
0111...111101 (30 bits total)

他にも例を示す:

                   ;         30ビットの2進数

(lsh 5 2)          ;   5  =  0000...000101
     ⇒ 20         ;      =  0000...010100
(ash 5 2)
     ⇒ 20
(lsh -5 2)         ;  -5  =  1111...111011
     ⇒ -20        ;      =  1111...101100
(ash -5 2)
     ⇒ -20
(lsh 5 -2)         ;   5  =  0000...000101
     ⇒ 1          ;      =  0000...000001
(ash 5 -2)
     ⇒ 1
(lsh -5 -2)        ;  -5  =  1111...111011
     ⇒ 268435454
                   ;      =  0011...111110
(ash -5 -2)        ;  -5  =  1111...111011
     ⇒ -2         ;      =  1111...111110
Function: logand &rest ints-or-markers

この関数は、引数の“論理積(logical and)”をreturnします。すべての引数のn番目のビットがセットされている場合に限り、結果のn番目のビットがセットされます(“セット”とは、そのビットの値が0ではなく1であることを意味します)。

たとえば、13と12の“論理積”は — 4ビット2進数を使用すると1101と1100の論理積は1100を生成します。この2進数では両方とも、左の2ビットがセット(つまり1)されているので、returnされる値の左2ビットがセットされます。しかし右の2ビットにたいしては、少なくとも1つの引数でそのビットが0なので、returnされる値の右2ビットは0になります。

したがって、

(logand 13 12)
     ⇒ 12

logandに何も引数も渡さなければ、値-1がリターンされる。-1を2進数で表すとすべてのビットが1なので、-1はlogandにたいする単位元(identity element)である。

                   ;        30ビット2進数

(logand 14 13)     ; 14  =  0000...001110
                   ; 13  =  0000...001101
     ⇒ 12         ; 12  =  0000...001100

(logand 14 13 4)   ; 14  =  0000...001110
                   ; 13  =  0000...001101
                   ;  4  =  0000...000100
     ⇒ 4          ;  4  =  0000...000100

(logand)
     ⇒ -1         ; -1  =  1111...111111
Function: logior &rest ints-or-markers

この関数は、引数の“論理和(inclusive or)”をreturnします。少なくとも1つの引数でn番目のビットがセットされていれば、結果のn番目のビットがセットされます。引数を与えない場合の結果は、この処理にたいする単位元である0です。logiorに渡す引数が1つだけの場合、その引数がreturnされます。

                   ;        30ビット2進数

(logior 12 5)      ; 12  =  0000...001100
                   ;  5  =  0000...000101
     ⇒ 13         ; 13  =  0000...001101

(logior 12 5 7)    ; 12  =  0000...001100
                   ;  5  =  0000...000101
                   ;  7  =  0000...000111
     ⇒ 15         ; 15  =  0000...001111
Function: logxor &rest ints-or-markers

この関数は、引数の“排他的論理和(exclusive or)”をreturnします。n番目のビットがセットされている引数の数が奇数個の場合だけ、結果のn番目のビットがセットされます。引数を与えない場合の結果は、この処理の単位元である0となります。logxorに渡す引数が1つだけの場合、その引数がreturnされます。

                   ;        30ビット2進数

(logxor 12 5)      ; 12  =  0000...001100
                   ;  5  =  0000...000101
     ⇒ 9          ;  9  =  0000...001001

(logxor 12 5 7)    ; 12  =  0000...001100
                   ;  5  =  0000...000101
                   ;  7  =  0000...000111
     ⇒ 14         ; 14  =  0000...001110
Function: lognot integer

この関数は引数の論理的な補数(logical complement)をreturnします。integern番目のビットが0の場合に限り、結果のn番目のビットが1になります。逆も成り立ちます。

(lognot 5)
     ⇒ -6
;;  5  =  0000...000101 (全部で30ビット)
;; becomes
;; -6  =  1111...111010 (全部で30ビット)

Next: , Previous: , Up: Numbers   [Contents][Index]