# 3.8 位运算

在计算机中，整数使用二进制数、位序列（零或一的数字）表示。从概念上讲，左边的位序列是无限的，最高有效位全为零或全为 1。按位运算会作用于此类序列的各个位。例如， 位移操作 会将整个序列向左或向右移动一个或多个位置。

Emacs Lisp 中的按位运算仅适用于整数。

Function：ash integer1 count ash(算术移位) 将integer1 中的位向左边移动count 位，如果count为负则向右移动。左移会在右边引入零位；右移则会丢弃最右边的位。视为等价的整数运算， ash将integer1乘以 2 的 count 次方，然后通过向下舍入将结果转换为整数。

以下是ash将位模式向左和向右移动一位的示例。这些示例仅显示二进制模式的低位；前导位都与所示的最高位一致。如您所见，左移一相当于乘以二，而右移一相当于除以二，然后向下舍入取整。

(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 integer1 count lsh，是logic shift的缩写，将integer1左移count位，如果count为负，则右移，使用 0 补位。如果 count为负，则integer1必须是 fixnum 或正的 bignum。此外，lsh 将 fixnum 连减两次 most-negative-fixnum ，将其处理为为无符号数字。这种古怪的行为可以追溯到 Emacs 只支持 fixnums 的时候。现在使用 ash 是更好的选择。

lsh的行为和ash很像，但当 integer1和 count1均为负时，以下的例子仅出现在这些特殊情况下。这些示例假定使用 30 位 fixnums。

```
             ;      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 此函数将参数进行按位与操作。

例如，使用 4 位二进制数，13 和 12 按位 与 结果为 12：1101 与 1100 按位 与 的 1100。在这两个二进制数中，最左边的两位都是 1，因此返回值的最左边的两位都是 1。但是，对于最右边的两位，其中一个参数是 0，因此返回值的最右边两位都是 0。

因此，

（logand 13 12） ⇒ 12 如果logand未传递任何参数，则返回值 -1。这个是一个logand的单位数字，因为它的二进制表示完全由 1 组成。如果只传递一个参数，则返回该参数。

```
               ;        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 该函数对参数进行按位或运算。如果没有参数，则结果为 0，这是此操作的恒定元素。如果只传递一个参数，则返回该参数。

```
               ;        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 此函数将参数按位异或。如果没有参数，则结果为 0，这是此操作的恒定元素。如果只传递一个参数，则返回该参数。

```
               ;        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 此函数将参数按位补码。结果和整数 -1 等价。

(lognot 5) ⇒ -6 ;; 5 = …000101 ;; becomes ;; -6 = …111010

Function：logcount integer 该函数返回整数的汉明权重：在那些的二进制表示的数量的整数。如果integer为负数，则返回其二进制补码表示中的零位数。结果总是非负的。

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