数字与算术运算
几乎你写的每一个程序都会用到数字。购物车要算总价,游戏要更新分数,脚本要统计某件事发生了多少次。Python 提供的算术运算符跟你在纸上做数学一样直观,另外还有几个值得一开始就了解的运算符。
各种运算符
数学中的四个基本运算符(+、-、*、/)表现跟你预期的完全一样。Python 还多加了三个你会经常用到的:整除、取余和幂运算。
price = 12.99
quantity = 3
print(price * quantity) # 38.97
print(price + 2) # 14.99
print(price - 1.00) # 11.99| 运算符 | 名称 | 示例 | 结果 |
|---|---|---|---|
+ | 加法 | 5 + 3 | 8 |
- | 减法 | 5 - 3 | 2 |
* | 乘法 | 5 * 3 | 15 |
/ | 除法 | 5 / 3 | 1.6666... |
// | 整除 | 5 // 3 | 1 |
% | 取余 | 5 % 3 | 2 |
** | 幂运算 | 5 ** 3 | 125 |
+、-、*、/ 的表现就跟纸上算数一样。另外三个值得早点学会:// 把结果向下取整为整数,% 给你余数,** 做幂运算。我用 % 的频率比我当初想的要高得多。 除法:/ 与 // 的区别
/ 永远给你精确的小数结果,即使答案是整数也一样。// 会去掉小数部分,并朝负无穷方向取整。对于正数来说,这就相当于砍掉小数;但对于负数来说,结果会比直接砍掉小数再多走一步,离零更远:
10 / 2 # 5.0 (永远是浮点数,即使能整除)
10 / 3 # 3.3333333333333335
10 // 3 # 3
7 // 2 # 3
-7 // 2 # -4 (朝负无穷方向取整,不是朝零方向)大多数情况下你用 // 处理的都是正数。等负数出现时,记住上面的这个行为就好。
/ 永远返回小数,即使能整除也一样:4 / 2 是 2.0。// 会去掉小数部分,但要留意负数:-7 // 2 是 -4,不是 -3,因为它是向下取整而不是直接砍掉小数。我第一次遇到的时候就被坑了。 取余运算符 %
% 给你的是整除之后剩下的部分。如果 10 // 3 是 3(因为 3 能装进 10 里三次),那么 10 % 3 就是 1(因为 3 × 3 = 9,10 - 9 = 1)。最常见的用法是判断一个数是奇数还是偶数。
10 % 3 # 1
10 % 2 # 0 (能整除)
10 % 7 # 3
6 % 2 # 0 (偶数)
7 % 2 # 1 (奇数)% 是整除之后剩下的部分。10 % 3 是 1,因为 3 能装进 10 里三次,还剩 1。你最常遇到它的场景是判断奇偶:n % 2 为 0 表示偶数,为 1 表示奇数。 幂运算 **
** 把一个数提升到某个次方。要用两个星号,不要用 ^ 符号(在 Python 中它另有含义):
2 ** 10 # 1024
3 ** 3 # 27
9 ** 0.5 # 3.0 (平方根:提升到 0.5 次方)** 把一个数提升到某个次方,所以 2 ** 10 是 1024。小数次方能给你开根号:9 ** 0.5 是 3.0。唯一的坑在符号上,要用 **,不要用 ^,后者在 Python 里做的是完全不同的事。 运算符优先级
Python 遵循标准的数学运算顺序:先算幂运算,再算乘除,最后算加减。如果你不确定,就用括号。括号能让意图一目了然,而且不需要付出任何代价:
2 + 3 * 4 # 14,不是 20
2 ** 3 + 1 # 9,不是 512
10 - 4 / 2 # 8.0,不是 3.0
(2 + 3) * 4 # 20
10 / (2 + 3) # 2.0int 和 float 如何互相影响
Python 有一条一致的规则:/ 永远返回小数,即使 4 / 2 也会给出 2.0。 只要一次运算中混入了整数和小数,结果也会是小数。如果你需要整数,就用 //,或者用 int() 转换。
4 / 2 # 2.0 (永远是 float)
4 // 2 # 2 (int)
4 + 2 # 6 (int)
4 + 2.0 # 6.0 (float)
4 * 0.5 # 2.0 (float)/ 永远给出小数,所以 4 / 2 是 2.0,不是 2。把整数和小数混在一起做任何运算,出来的都是小数。当你需要整数时,用 //,或者用 int() 包一层。 浮点数精度
有一个几乎每个人早晚都会撞上的坑:
0.1 + 0.2 # 0.30000000000000004这个微小的误差不是 Python 的 bug。计算机用二进制存储小数,而像 0.1 这样的值没法精确表示。这跟 1/3 没法用小数精确写出来是同一个道理。对大多数日常计算来说这无关紧要。要展示金额的话,用 round() 或者 :.2f 格式说明符就能让输出显得整齐。
0.1 这样的值没有精确的二进制形式,所以 0.1 + 0.2 会得到 0.30000000000000004。这不是 Python 的 bug,每种语言都是这样。日常输出的话,用 round() 或 :.2f 就能让它显得整齐。 更易读的数字写法
Python 允许你在数字字面量中插入下划线,让大数字更容易读。Python 会完全忽略这些下划线,它们只是为了方便你看:
population = 8_100_000_000
distance_km = 384_400
pi_approx = 3.141_592_6538_100_000_000 跟 8100000000 是同一个值。Python 会完全忽略这些下划线,它们是给你的眼睛看的,不是给解释器看的。 有用的内置函数
abs()
abs() 返回绝对值:结果永远是正数,跟输入的符号无关。当你关心一个数离零有多远、而不关心方向时,就用它。
abs(-5) # 5
abs(3.7) # 3.7
abs(-0.5) # 0.5abs() 去掉符号,只给你正数大小:abs(-5) 是 5,abs(3.7) 是 3.7。当你只关心一个数离零有多远、不关心它偏向哪个方向时就用它。 round()
round() 默认四舍五入到最接近的整数。传入第二个参数就能保留指定位数的小数:
round(3.7) # 4
round(3.2) # 3
round(3.14159, 2) # 3.14有一点值得知道:round(2.5) 给出的是 2,不是 3。当一个值恰好处在两个选项正中间时,Python 会向最接近的偶数取整。
round(x) 舍入到最接近的整数,round(x, n) 保留 n 位小数。意外之处在于:恰好处在正中间的值会舍入到最接近的偶数,所以 round(2.5) 是 2,不是 3。 divmod()
divmod() 在一次调用里同时给你商和余数。它返回一对值,也就是一个元组(在元组和集合这一章会讲到),你可以一次性把它赋值给两个变量:
divmod(10, 3) # (3, 1):商 3,余数 1
divmod(7, 2) # (3, 1)
divmod(9, 3) # (3, 0)
quotient, remainder = divmod(10, 3)
print(quotient) # 3
print(remainder) # 1divmod(a, b) 把商和余数一起给你:divmod(10, 3) 是 (3, 1)。你可以用 quotient, remainder = divmod(10, 3) 一次性把两者都拆出来。 实战演练
一个小费计算器:
bill = 45.50
tip_rate = 0.18
tip = round(bill * tip_rate, 2)
total = round(bill + tip, 2)
print(f"账单:${bill}")
print(f"小费:${tip}")
print(f"总计:${total}")round() 让输出看起来像一笔金额,而不是一长串小数位。

