# Python 运算符：算术、整除 // 与取余 %、比较、and/or/not 以及 python round

URL: https://skillaria.top/zh/guides/python/python-operators-round-floor-ceil

在 Python 中，/ 总是得到 float，// 向下取整得到整数部分，% 是余数，** 是幂。round(x, n) 按「银行家舍入」保留 n 位小数：round(2.5) 得到 2，round(3.5) 得到 4；向上和向下取整分别使用 math.ceil 和 math.floor，绝对值则由 abs 给出。

Python 运算符是把值变成新值的符号：`+` 做加法，`//` 做整除，`and` 把条件连接起来。下面给出完整的运算符列表和示例，说明 `/` 与 `//` 的区别、`and`、`or`、`not` 的逻辑，以及取整函数：python round、`math.ceil`、`math.floor` 和 `abs`。所有示例都可以粘贴到 REPL 中验证。

## Python 运算符列表

运算符按用途分组。不必整张表都背下来：实际代码中最常见的是算术、比较和逻辑连接。

| 分组 | 运算符 | 示例 |
| --- | --- | --- |

| 算术 | `+ - * / // % **` | `7 // 2` → 3 |

| 比较 | `== != < > <= >=` | `3 < 5` → True |

| 逻辑 | `and or not` | `not True` → False |

| 同一性 | `is`、`is not` | `x is None` |

| 成员 | `in`、`not in` | `"咖" in "咖啡"` → True |

| 赋值 | `= += -= *= /= //= %= **=` | `total += 250` |

| 海象运算符 | `:=` | `if (n := len(s)) > 10:` |

| 位运算 | `& | ^ ~ << >>` | `5 & 3` → 1 |

## 算术运算符

加、减、乘的用法和数学课上一样。只要表达式中有一个 `float`，结果也是 `float`：`2 + 1.0` 得到 `3.0`。Python 的整数不会溢出：`2 ** 100` 会被精确计算，无论有多少位数字。

```
>>> 250 + 120
370
>>> 12.5 * 3
37.5
>>> 2 ** 10
1024
>>> 2 ** 0.5
1.4142135623730951
```

### Python 中的幂运算：** 运算符

乘方使用两个星号，而不是 `^`：在 Python 中 `^` 表示按位异或，因此 `2 ^ 3` 得到的是 1，而不是 8。分数指数可以求根：`9 ** 0.5` 得到 `3.0`。还有函数 `pow(x, y)`，效果相同；它的第三个参数用于取模：`pow(2, 10, 1000)` 得到 24。

注意优先级：`**` 的优先级高于一元负号，所以 `-2 ** 2` 等于 `-4`。如果想求负数的平方，请加括号：`(-2) ** 2`。

## Python 中的除法：/、// 和 %

Python 有两种除法，这是新手最常遇到的意外来源。普通除法 `/` 总是返回 `float`，即使能整除也一样。整除 `//` 去掉小数部分，而 `%` 返回余数。

```
>>> 7 / 2
3.5
>>> 8 / 2
4.0
>>> 7 // 2
3
>>> 7 % 2
1
```

### 整除 // 与取余 %：实际应用

`//` 和 `%` 组合起来可以解决「整数部分是多少、还剩多少」的问题。课程中的开销记录器把金额存为分，以免丢失精度，然后把总额拆分为元和分：

```
kopecks = 125050          # 以分为单位存储金额
rub = kopecks // 100      # 1250 — 整数部分（元）
kop = kopecks % 100       # 50 — 余数（分）
print(rub, kop)           # 1250 50

print(40 // 7, "周零", 40 % 7, "天")   # 5 周零 5 天
```

内置函数 `divmod` 一次返回两个结果：`divmod(125050, 100)` 得到元组 `(1250, 50)`。余数也可以用来判断奇偶：`n % 2 == 0` 对偶数为真。

### 负数：// 向下取整

运算符 `//` 不只是去掉小数，而是向下取整，即趋向负无穷。对正数没有区别，对负数则不同。Python 中余数 `%` 的符号与除数相同，因此总有 `a == (a // b) * b + a % b` 成立。

```
>>> -7 // 2
-4
>>> -7 % 2
1
>>> int(-7 / 2)     # 去掉小数部分，而不是向下取整
-3
```

### 除以零：会出现什么错误

用三种运算符中的任何一种除以零，都会抛出 `ZeroDivisionError` 异常。整数和小数都一样。可以用 `try/except` 捕获，也可以事先检查除数。

```
>>> 10 / 0
Traceback (most recent call last):
  ...
ZeroDivisionError: division by zero
>>> count = 0
>>> avg = 1500 / count if count else 0
>>> avg
0
```

## 比较运算符

比较运算的结果是 `True` 或 `False`。判断相等使用两个等号 `==`，单个 `=` 是赋值。字符串按字符编码逐个比较，所以 `"Z" < "a"` 为真：大写字母排在小写字母之前。

```
>>> 250 == 250.0
True
>>> 3 != 4
True
>>> 1 < 5 > 0.1 + 0.2 == 0.3
False
```

像 `0 <= x < 100` 这样的链式比较是 Python 的一个便利特性，不需要写 `and`。最后一行提醒你小数的误差：`0.1 + 0.2` 的结果是 `0.30000000000000004`。比较小数时请使用 `math.isclose(a, b)`，金额则应存为分或使用 `Decimal`。

## 逻辑运算符 and、or、not

Python 的逻辑运算符是英文单词，而不是其他语言中的 `&&` 和 `||`。`and` 在两边都为真时为真，`or` 在至少一边为真时为真，`not` 对值取反。

| a | b | a and b | a or b | not a |
| --- | --- | --- | --- | --- |

| True | True | True | True | False |

| True | False | False | True | False |

| False | True | False | True | True |

| False | False | False | False | True |

优先级：先 `not`，然后 `and`，最后 `or`。表达式 `True or False and False` 的结果是 `True`，因为 `and` 先计算。复杂条件中请加括号，这样你和同事都更容易读懂。

### and 与 or 实际返回什么

`and` 和 `or` 返回的不一定是 `True` 或 `False`，而是其中的一个操作数。`or` 返回第一个为真的值（如果都不为真，则返回最后一个），`and` 返回第一个为假的值（如果都为真，则返回最后一个）。被视为假的值有：`0`、`0.0`、空字符串、空集合、`None` 和 `False`。

```
>>> name = ""
>>> name or "访客"
'访客'
>>> 5 and 0
0
>>> not ""
True
```

求值是惰性的：如果左边已经决定了结果，右边就不会被计算。因此当 `count == 0` 时，`count and total / count` 不会因除以零而出错。与另外两个不同，`not` 总是返回 `bool`。

## is 与 in 运算符

`==` 比较的是值，而 `is` 检查两个名字是否指向同一个对象。两个内容相同的空购物篮相等，但它们不是同一个对象。`is` 最常用的场景是判断 `None`：`if x is None`。

```
>>> a = [250, 120]
>>> b = [250, 120]
>>> a == b, a is b
(True, False)
>>> c = a
>>> c is a
True
```

不要用 `is` 比较数字或字符串：有时它「碰巧」能用，是因为解释器对对象做了缓存，但结果依赖具体实现；对于 `x is 5` 这样的写法，Python 还会发出 `SyntaxWarning`。

运算符 `in` 检查成员关系：字符串中的子串、列表中的元素、字典中的键。`not in` 则相反。

```
>>> "咖啡" in "咖啡和点心"
True
>>> "餐饮" in {"餐饮": 450, "打车": 300}
True
>>> 5 not in [1, 2, 3]
True
```

## 赋值运算符与海象运算符 :=

复合赋值 `+=`、`-=`、`*=`、`//=` 等是简写：`total += 250` 等同于 `total = total + 250`。Python 没有 `++` 和 `--` 运算符：写 `x++` 会导致语法错误。

海象运算符 `:=`（因为它看起来像海象的眼睛和獠牙而得名）可以在表达式内部完成赋值。当你既需要检查一个值，又需要在之后使用它时，它很有用：

```
items = ["咖啡", "打车", "午饭", "电影"]
if (n := len(items)) > 3:
    print(f"支出条目太多：{n}")

while (line := input("金额：")) != "":
    print(int(line) * 2)
```

没有海象运算符的话，就得调用两次 `len`，或者把赋值单独写成一行。不要滥用它：如果一行代码变得难以阅读，普通赋值更好。

## Python 中的取整：round、ceil、floor

Python 的取整工具包括内置函数 `round` 以及 `math` 模块中的函数。它们解决的是不同问题，混淆它们是常见错误。

| 函数 | 作用 | 2.5 | -2.5 | 2.7 |
| --- | --- | --- | --- | --- |

| `round(x)` | 四舍五入到最近的整数，恰好一半时取偶数 | 2 | -2 | 3 |

| `math.floor(x)` | 向下，趋向负无穷 | 2 | -3 | 2 |

| `math.ceil(x)` | 向上，趋向正无穷 | 3 | -2 | 3 |

| `math.trunc(x)`、`int(x)` | 去掉小数部分，趋向零 | 2 | -2 | 2 |

### Python 的 round 函数与银行家舍入

函数 `round(x, n)` 保留 `n` 位小数；如果省略第二个参数，则返回整数 `int`。最容易踩的坑是：python round 采用「银行家舍入」，即恰好一半时舍入到最近的偶数。因此 `round(2.5)` 得到 2，而 `round(3.5)` 得到 4。这样在大量计算中，舍入误差不会总朝同一个方向累积。

```
>>> round(2.5), round(3.5)
(2, 4)
>>> round(3.14159, 2)
3.14
>>> round(1250, -2)     # 精确到百位
1200
>>> round(2.675, 2)     # 不是 2.68：二进制下它是 2.67499...
2.67
```

如果需要中学里习惯的「五入」，例如在收据中，请使用 `Decimal` 配合 `ROUND_HALF_UP` 模式。数字要以字符串形式传入，以免继承 `float` 的误差：

```
>>> from decimal import Decimal, ROUND_HALF_UP
>>> Decimal("2.5").quantize(Decimal("1"), ROUND_HALF_UP)
Decimal('3')
>>> Decimal("2.675").quantize(Decimal("0.01"), ROUND_HALF_UP)
Decimal('2.68')
```

课程中还有一条规则：只在输出时取整。要美观地打印，不需要 `round`，用 f 字符串就够了：`f"{amount:.2f}"` 显示两位小数，而数值本身保持精确。

### math.ceil 与 math.floor：向上和向下取整

当「不够」是不可接受的时候，就用 `math.ceil`：例如要订几辆大巴、需要多少页才能放下所有结果。`math.floor` 则用于只计算完整单位的场景。两个函数都返回 `int`。

```
import math

guests = 47
seats = 20
print(math.ceil(guests / seats))   # 3 辆大巴
print(math.floor(9.99))            # 9
print(-(-guests // seats))         # 3 — 不用 math 实现 ceil，靠 // 的技巧
```

模块 `math` 中还有其他有用的函数：`math.sqrt`（平方根）、`math.isclose`（比较小数）、`math.pi`、`math.gcd`。Python 3.15 新增了子模块 `math.integer`（PEP 791），用于整数运算：其中有 `comb`、`factorial`、`gcd`、`isqrt`、`lcm`、`perm`，而旧的 `math.gcd` 等仍然可用。

## abs 函数：数的绝对值

`abs(x)` 返回绝对值，即去掉符号后与零的距离。这是内置函数，无需导入。它适用于整数、小数，甚至复数：对于 `3+4j`，它返回向量的长度 `5.0`。

```
>>> abs(-250)
250
>>> abs(-12.5)
12.5
>>> budget, spent = 5000, 5320
>>> abs(budget - spent)    # 偏差了多少
320
```

典型用法是忽略方向的差值，以及带容差的比较：`abs(a - b) < 0.001`。对于小数，`math.isclose` 更可靠，因为它会考虑数值的量级。

## 运算符优先级

一个表达式中有多个运算符时，Python 按优先级从高到低执行：

1. `**`
2. 一元运算符 `-x`、`+x`、`~x`
3. `* / // %`
4. `+ -`
5. 位移与位运算
6. 比较、`in`、`is`
7. `not`
8. `and`
9. `or`
10. `:=`

例如 `2 + 3 * 4` 等于 14，而 `(2 + 3) * 4` 等于 20。拿不准时就加括号：多余的括号没有任何代价，而优先级错误却很难找到。

## 运算符的常见错误

| 错误 | 实际发生的情况 | 正确写法 |
| --- | --- | --- |

| `if x = 5:` | SyntaxError：这是赋值语句 | `if x == 5:` |

| 用 `2 ^ 3` 求幂 | 按位异或，结果为 1 | `2 ** 3` |

| 期望 `8 / 2` 得到整数 | 得到 `4.0` | `8 // 2` |

| `x == 1 or 2` | 总是为真：`or 2` 恒为真 | `x in (1, 2)` |

| 期望 `round(2.5)` 得到 3 | 银行家舍入结果为 2 | 使用 `Decimal` 配合 `ROUND_HALF_UP` |

| `"5" + 5` | TypeError | `int("5") + 5` |

## 总结

记住最关键的几点：`/` 总是得到 float，`//` 向下取整，`%` 返回与除数同号的余数，乘方用 `**`。逻辑运算符 `and`、`or`、`not` 用英文单词书写并惰性求值，`is` 用于判断 `None`。Python 的 round 按偶数舍入，向上和向下取整分别用 `math.ceil` 和 `math.floor`，绝对值由 `abs` 给出。本课程会在实践中讲解这些运算符，例如用分来存储金额的开销记录器。

## FAQ

**如何在 Python 中保留两位小数？**

使用 round(x, 2)；如果只是想美观地输出，用 f 字符串 f"{x:.2f}"，它不会改变数值本身。

**为什么 Python 中 round(0.5) 得到 0？**

因为 round 在恰好一半时舍入到最近的偶数，而 0 是偶数；同理 round(1.5) 和 round(2.5) 都得到 2。

**如何在 Python 中得到除法的整数部分？**

使用 //：17 // 5 得到 3。对负数它向下取整，所以 -17 // 5 得到 -4；如果想让结果向零截断，请使用 int(-17 / 5)。

**Python 有三元运算符吗？**

有，它是条件表达式：值1 if 条件 else 值2，例如 "偶数" if n % 2 == 0 else "奇数"。

**Python 中 & 和 and 有什么区别？**

and 是逻辑运算符，带惰性求值；& 是整数的按位与，也是集合的交集。在 if 条件中请使用 and。


---
Source: Skillaria.Top (https://skillaria.top)
