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


3.8 整数にたいするビット演算

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

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

Function: ash integer1 count

ash (算術シフト(arithmetic shift))は、integer1の中のビット位置を左にcountシフトする。countが負なら右にシフトする。左シフトでは右側に0が挿入されて、右シフトでは最右ビットが破棄される。整数処理として考えると、ashinteger1を 2**count 乗じてから下方、負の無限大に向かって丸めることにより結果を変換する。

以下はビットパターンを1ビット左にシフトしてから右にシフトする例。この例で2進数パターンの下位ビットだけを示している。先行ビットは表示されている上位ビットにすべて一致する。確認できるように1ビットの左シフトは2を乗じて、右シフトは2で除してから負の無限大方向に丸められる。

(ash 7 1) ⇒ 14
;; 10進の7は10進の14になる
…000111
     ⇒
…001110

(ash 7 -1) ⇒ 3
…000111
     ⇒
…000011

(ash -7 1) ⇒ -14
…111001
     ⇒
…110010

(ash -7 -1) ⇒ -4
…111001
     ⇒
…111100

以下は2ビット左にシフトしてから右に2ビットシフトする例:

                  ;         2進数値
(ash 5 2)         ;   5  =  …000101
     ⇒ 20         ;      =  …010100
(ash -5 2)        ;  -5  =  …111011
     ⇒ -20        ;      =  …101100
(ash 5 -2)
     ⇒ 1          ;      =  …000001
(ash -5 -2)
     ⇒ -2         ;      =  …111110
Function: lsh integer1 count

lshlogical shiftの略で、integer1のビットを左にcountシフトする。countが負ならinteger1はfixnumか正のbignumのいずれかでなければならず、lshはシフト前に負のfixnumをmost-negative-fixnumで2回減算してあたかも符号なしであるかのように非負の結果を生成する。この奇妙な振る舞いはEmacsがfixnumsだけをサポートしていた頃の振る舞いであり、現在ではashがより良い選択である。

integer1count1がいずれも負の場合を除いてlshashのように振る舞うので、以下の例ではこれらの例外ケースに焦点をあてている。これらの例は30ビットのfixnumsを想定している。

                 ;      2進数値
(ash -7 -1)      ; -7 = …111111111111111111111111111001
     ⇒ -4        ;    = …111111111111111111111111111100
(lsh -7 -1)
     ⇒ 536870908 ;    = …011111111111111111111111111100
(ash -5 -2)      ; -5 = …111111111111111111111111111011
     ⇒ -2        ;    = …111111111111111111111111111110
(lsh -5 -2)
     ⇒ 268435454 ;    = …001111111111111111111111111110
Function: logand &rest ints-or-markers

この関数は引数のビットのANDをリターンする。すべての引数のn番目のビットが1の場合に限り、結果のn番目のビットが1となる。

たとえば13と12では、4ビット2進数を使用すると1101と1100のビットANDは1100を生成する。この2進数ではいずれも左の2ビットがセット(つまり1)されているので、リターンされる値の左2ビットがセットされる。しかし右の2ビットにたいしては少なくとも1つの引数でそのビットが0なので、リターンされる値の右2ビットは0になる。

したがって、

(logand 13 12)
     ⇒ 12

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

                   ;        2進数値

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

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

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

この関数は、引数のビット単位の包含的ORをリターンする。少なくとも1つの引数でn番目のビットが1なら、結果のn番目のビットが1になる。引数を与えなければ、結果はこの処理にたいする単位元である0となる。logiorに渡す引数が1つだけならその引数がリターンされる。

                   ;        2進数値

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

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

この関数は、引数のビット単位の排他的ORをリターンする。n番目のビットが1であるような引数の数が奇数個の場合のみ、結果のn番目のビットが1となる。引数を与えなければ、結果はこの処理の単位元である0となる。logxorに渡す引数が1つだけならその引数がリターンされる。

                   ;        2進数値

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

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

この関数は引数のビット単位の補数(bitwise complement)をリターンする。integern番目のビットが0の場合に限り、結果のn番目のビットが1になり、その逆も成り立つ。結果は-1 - integerと等価。

(lognot 5)
     ⇒ -6
;;  5  =  …000101
;; becomes
;; -6  =  …111010
Function: logcount integer

この関数はintegerハミング重み (Hamming weight: integerの2進数表現での1の個数)をリターンする。integerが負なら、その2の補数の2進数表現での0ビットの個数をリターンする。結果は常に非負となる。

(logcount 43)     ;  43 = …000101011
     ⇒ 4
(logcount -43)    ; -43 = …111010101
     ⇒ 3

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