3.8 整数的按位运算

在计算机中,整数以二进制数表示,即由若干 bits位(取值为 0 或 1 的数字)组成的序列。从概念上讲,该位序列在左侧是无限延伸的,最高位全为 0 或全为 1。按位运算会对该序列中的每一位单独操作。例如, shifting移位 操作会将整个序列向左或向右移动一位或多位,并保持原有模式。 Emacs Lisp 中的按位运算仅适用于整数。

Function: ash integer count

asharithmetic shift算术移位)将整数 integer 的二进制位向左移动 count 位;若 count 为负数,则向右移动。左移会在右侧补 0;右移会丢弃最右侧的位。从整数运算角度看,ash 等价于将 integer 乘以 2**count, 然后向下取整(向负无穷方向)得到整数结果。

下面是 ash 分别左移、右移一位的示例。示例只展示低位二进制位,高位均与所示最高位保持一致。可以看到,左移一位等价于乘以 2,右移一位等价于除以 2 并向负无穷取整。

(ash 7 1) ⇒ 14
;; Decimal 7 becomes decimal 14.
...000111
     ⇒
...001110

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

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

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

左移或右移两位的示例:

                  ;         binary values
(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 integer count

lshlogical shift逻辑移位的缩写,将整数 integer 向左移动 count 位;若 count 为负数,则向右移动,空出的位一律补 0。若 count 为负,则 integer 必须是定长数(fixnum)或正的大数(bignum),且 lsh 会将负定长数视为无符号数处理:先减去两倍的 most-negative-fixnum 再移位,结果非负。这种特殊行为源于早期 Emacs 仅支持定长数的时代;现在更推荐使用 ash

除了 integercount 同时为负的情况外,lshash 行为一致。下面示例聚焦这些例外情况,并假设使用 30 位定长数。

                 ;      binary values
(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

该函数返回所有参数的按位与结果:当且仅当所有参数的第 n 位都为 1 时,结果的第 n 位为 1。

例如,用 4 位二进制数表示,13 与 12 的按位与结果是 12:1101 与 1100 运算得到 1100。两个数最左侧两位都为 1,因此结果最左侧两位为 1;而最右侧两位至少有一个参数为 0,因此结果最右侧两位为 0。

所以,

(logand 13 12)
     ⇒ 12

logand 无参数,返回 −1。该 logand 数是按位与的单位元,因为其二进制全为 1。若 logand 只传入一个参数,直接返回该参数。

                   ;        binary values

(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

该函数返回所有参数的按位或结果:当且仅当至少一个参数的第 n 位为 1时,结果的第 n 位为 1。无参数时返回 0,是该运算的单位元。logior 只传入一个参数时,直接返回该参数。

                   ;        binary values

(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

该函数返回所有参数的按位异或结果:当且仅当该位为 1 的参数个数是奇数时,结果的第 n 位为 1。无参数时返回 0,是该运算的单位元。logxor 只传入一个参数时,直接返回该参数。

                   ;        binary values

(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

该函数返回参数的按位取反结果:当且仅当 integer 的第 n 位为 0时,结果的第 n 位为 1,反之亦然。结果等于:−1 − integer

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

该函数返回 integer整数Hamming weight汉明重量:即 integer 二进制表示中 1 的个数。若 integer 为负数,则返回其二进制补码表示中 0 的个数。结果始终非负。

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

emacs

Emacs

org-mode

Orgmode

Donations

打赏

Copyright

© 2025 Jasper Hsu

Creative Commons

Creative Commons

Attribute

Attribute

Noncommercial

Noncommercial

Share Alike

Share Alike