# 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


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://emacs-lisp.ivory.cafe/shu-zi/wei-yun-suan.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
