当前位置:

首页 > 编程开发 > Python基础指南之算术运算符与优先级规则详解

Python基础指南之算术运算符与优先级规则详解

Python算术运算符包括加减乘除、整除、取模和幂运算。除法始终返回浮点数,整除向下取整,取模结果符号与除数一致。幂运算是右结合,优先级高于一元负号。浮点数存在精度问题,可用Decimal或math.isclose处理。复合赋值运算符对可变对象原地修改。运算符优先级从高到低为:括号、幂、一元正负号、乘除模、加减。

一、开篇:看似简单实则暗藏玄机的算术运算符

每天我们都在写 a + ba * b 这样的表达式,看起来简单得不能再简单了。不过,你真的确定自己掌握了所有细节吗?

Python基础指南之算术运算符与优先级规则详解

先来测几道题,热热身:

# 题1:猜猜输出什么?
print(10 / 3)      # ?
print(10 // 3)     # ?
print(10 % 3)      # ?
print(10 ** 3)     # ?

# 题2:这个表达式的结果是什么?
result = 2 + 3 * 4 ** 2 - 8 / 2
# 你能心算出来吗?

# 题3:为什么这个结果不是0.3?
print(0.1 + 0.2)   # 输出什么?

如果对其中任何一个问题拿不准,说明你对算术运算符的理解还有上升空间。今天这篇文章,咱们就来系统性地把 Python 中所有的算术运算符,以及控制表达式计算顺序的优先级规则,彻底捋清楚。

二、Python的算术运算符全家福

2.1 七种基本算术运算符

# Python共有7种算术运算符

# 1. 加法 +
print(10 + 3)     # 13

# 2. 减法 -
print(10 - 3)     # 7

# 3. 乘法 *
print(10 * 3)     # 30

# 4. 除法 /  —— 总是返回浮点数
print(10 / 3)     # 3.3333333333333335(注意:不是3!)

# 5. 整除 // —— 向下取整
print(10 // 3)    # 3

# 6. 取模(取余) %
print(10 % 3)     # 1

# 7. 幂运算 **
print(10 ** 3)    # 1000

2.2 除法 / —— 总是返回浮点数

关键变化来了:Python 3 中 / 永远是浮点数除法,这和 Python 2 的整数除法不同。很多从 Python 2 转过来的老手,刚上手时都踩过这个坑。

# Python 3:/ 总是返回浮点数
print(10 / 5)     # 2.0——不是2!
print(10 / 3)     # 3.3333333333333335
print(1 / 3)      # 0.3333333333333333
print(type(10 / 2))  # 

# 即使能整除,也是浮点数
result = 4 / 2
print(f'{result}, type={type(result).__name__}')  # 2.0, type=float

# 如果需要整数结果,用 //
print(10 // 5)    # 2(int类型)
print(type(10 // 5))  # 

2.3 整除 // —— 向下取整

整除运算符 // 的结果是向下取整(floor),而不是向零取整。这一点在处理负数时特别容易翻车。

# 正数——向下取整=截断小数部分
print(10 // 3)    # 3
print(10 // 4)    # 2

# 负数——向下取整≠向零取整!
print(-10 // 3)   # -4(不是-3!)
# 因为-10/3 = -3.333...,向下取整得到-4

# 对比其他语言的向零取整:
# C/Ja va中 -10/3 = -3(向零取整,截断小数)
# Python中 -10//3 = -4(向下取整)

# 图示:
# -4  -3  -2  -1   0   1   2   3
#  |---|---|---|---|---|---|---|
#     ↑-3.33  向下取整到-4

# 验证
print(-10 / 3)     # -3.3333333333333335
print(-10 // 3)    # -4

# 更多负数例子
print(-7 // 3)     # -3(-7/3=-2.333...,向下取整得-3)
print(-3 // 3)     # -1(正好整除)
print(-1 // 3)     # -1(-1/3=-0.333...,向下取整得-1)

2.4 取模 % —— 和整除配套

取模运算有一个很漂亮的恒等式:a = b * (a // b) + (a % b)。理解了它,取模的符号问题就迎刃而解。

# 取模和整除的关系
# a = b * (a // b) + (a % b)

a, b = 10, 3
print(f'{a} = {b} * ({a // b}) + ({a % b})')  # 10 = 3 * 3 + 1

# 对于负数,这个恒等式依然成立
a, b = -10, 3
print(f'{a} = {b} * ({a // b}) + ({a % b})')  # -10 = 3 * (-4) + 2
# 注意:-10 % 3 = 2(不是1!)

# 所以取模结果的符号总是和除数相同
print(-10 % 3)     # 2(除数3为正,结果为正)
print(10 % -3)     # -2(除数-3为负,结果为负)
print(-10 % -3)    # -1(除数-3为负,结果为负)

# 常用场景:循环索引
# 无论index多大,index % len 都在[0, len-1]范围内
items = ['a', 'b', 'c']
for i in range(10):
    print(items[i % len(items)], end=' ')  # a b c a b c a b c a
print()

2.5 幂运算 ** —— 右结合

幂运算符 **右结合的,意味着多个 ** 从右向左计算。这一点和数学中的幂运算习惯一致,但很容易被忽视。

# 幂运算——**是右结合的
# 2 ** 3 ** 2 = 2 ** (3 ** 2) = 2 ** 9 = 512
# 不是 (2 ** 3) ** 2 = 8 ** 2 = 64!

print(2 ** 3 ** 2)  # 512
print(2 ** (3 ** 2))  # 512——等价于上面的
print((2 ** 3) ** 2)  # 64——加括号后不同

# 常用场景
print(2 ** 10)     # 1024(2的10次方)
print(16 ** 0.5)   # 4.0(平方根)

# ⚠️ 幂运算优先级高于一元负号
print(-2 ** 2)     # -4(等价于 -(2**2))
print((-2) ** 2)   # 4(加括号改变了计算顺序)

# 这个行为经常让人困惑!
# -2 ** 2 → -(2 ** 2) → -4
# 而不是 (-2) ** 2 → 4

三、算术运算符的特殊行为

3.1 字符串和序列的算术运算

# 字符串——支持 + 和 *
print('Hello' + ' ' + 'World')  # Hello World(拼接)
print('Ha' * 5)                 # HaHaHaHaHa(重复)

# 列表——支持 + 和 *
print([1, 2] + [3, 4])         # [1, 2, 3, 4](合并)
print([0] * 5)                 # [0, 0, 0, 0, 0](重复)

# 元组——支持 + 和 *
print((1, 2) + (3, 4))         # (1, 2, 3, 4)
print(('Hi',) * 3)             # ('Hi', 'Hi', 'Hi')

# ⚠️ 字符串不支持 - 和 *与*(两个字符串相乘)
# 'Hello' - 'lo'  # TypeError
# 'Hello' * 'World'  # TypeError

3.2 浮点数精度问题

这是新手最容易碰到的“鬼故事”:明明数学上 0.1 + 0.2 = 0.3,但在 Python 里 0.1 + 0.2 却是 0.30000000000000004。原因很简单——二进制无法精确表示某些十进制小数,就像十进制无法精确表示 1/3 一样。下面是几种靠谱的解决方案。

# ⚠️ 浮点数运算的精度问题——二进制无法精确表示某些十进制小数
print(0.1 + 0.2)       # 0.30000000000000004——不是精确的0.3!
print(0.1 + 0.2 == 0.3)  # False!

# 原因:0.1和0.2在二进制中是无限循环小数
# 类似于十进制中的1/3 = 0.333333...
# 计算机用有限位数存储,所以有舍入误差

# 解决方案一:使用Decimal(精确十进制运算)
from decimal import Decimal
print(Decimal('0.1') + Decimal('0.2'))  # 0.3——精确!

# 解决方案二:使用math.isclose做近似比较
import math
print(math.isclose(0.1 + 0.2, 0.3))   # True

# 解决方案三:用round控制精度
print(round(0.1 + 0.2, 10))  # 0.3

# 解决方案四:整數運算(用分代替元)
amount_cents = 10 + 20  # 0.10元 + 0.20元 = 30分
print(f'{amount_cents / 100:.2f}元')  # 0.30元

3.3 大整数运算不受精度限制

# Python的整数是任意精度的——不受限于32位或64位
# 你可以计算任意大的整数

# 计算2的100次方
big = 2 ** 100
print(big)  # 1267650600228229401496703205376
print(type(big))  # 

# 计算100的阶乘
factorial_100 = 1
for i in range(1, 101):
    factorial_100 *= i
print(f'100! = {factorial_100}')

# 浮点数没有这个待遇——受限于64位IEEE 754
print(2.0 ** 1024)  # OverflowError(在某些实现中返回inf)

# 这就是为什么Python在科学计算和大数运算中特别受欢迎

3.4 复数运算

# Python原生支持复数运算
a = 3 + 4j
b = 1 - 2j

# 加减乘除
print(a + b)       # (4+2j)
print(a - b)       # (2+6j)
print(a * b)       # (11-2j)
print(a / b)       # (-1+2j)

# 取模
print(abs(a))      # 5.0(sqrt(3²+4²))

# 共轭
print(a.conjugate())  # (3-4j)

# 实部和虚部
print(a.real)      # 3.0
print(a.imag)      # 4.0

四、复合赋值运算符

4.1 所有复合赋值运算符

复合赋值运算符把运算和赋值合二为一,写起来更简洁。不过要注意,对可变对象和不可变对象,它的行为有微妙差别。

# 完整列表
x = 10

x += 3   # x = x + 3  → 13
x -= 3   # x = x - 3  → 10
x *= 3   # x = x * 3  → 30
x /= 3   # x = x / 3  → 10.0
x //= 3  # x = x // 3 → 3.0
x %= 3   # x = x % 3  → 0.0
x **= 3  # x = x ** 3 → 0.0

# 对于字符串/列表
s = 'Hello'
s += ' World'   # s = s + ' World'
print(s)         # Hello World

lst = [1, 2]
lst *= 3         # lst = lst * 3
print(lst)       # [1, 2, 1, 2, 1, 2]

4.2 复合赋值的微妙之处

# += 对可变对象是原地修改
lst1 = [1, 2, 3]
original_id = id(lst1)
lst1 += [4, 5]  # 等价于 lst1.extend([4, 5])
print(f'lst1: {lst1}, id不变: {id(lst1) == original_id}')  # True——原地修改

# 对比:lst1 = lst1 + [4, 5] 创建新对象
lst2 = [1, 2, 3]
original_id = id(lst2)
lst2 = lst2 + [4, 5]  # 创建新列表
print(f'lst2: {lst2}, id不变: {id(lst2) == original_id}')  # False——新对象

# ⚠️ 对于不可变类型,+= 总是创建新对象
x = 10
original_id = id(x)
x += 5  # 等价于 x = x + 5,创建了新整数
print(f'id不变: {id(x) == original_id}')  # False

五、运算符优先级规则

5.1 优先级从高到低

# Python算术运算符优先级(从高到低):
# 1. () 括号
# 2. ** 幂运算
# 3. +x, -x 一元正负号
# 4. *, /, //, % 乘除模
# 5. +, - 加减

# 口诀:括号→幂→正负→乘除→加减
# 和小学数学的"先乘除后加减"一致,多了幂和符号优先级需要注意的地方

来看几个具体例子——按优先级一步步展开会更清楚:

# 示例1:经典测试题 2 + 3 * 4 = 14

result = 2 + 3 * 4.  # Python里不允许写成整句带点号的表达式?这里应为2+3*4
print(f'2 + 3 * 4 = {result}')  # 14(先乘后加)


# 示例2:括号改变了一切
result = (2 + 3) * 4
print(f'(2 + 3) * 4 = {result}')  # 20(括号优先)

# 示例3:幂优先于乘
result = 2 ** 3 * 4
print(f'2 ** 3 * 4 = {result}')  # 32(幂优先于乘)

# 示例4:负号和幂的坑
result = -2 ** 2
print(f'-2 ** 2 = {result}')  # -4(幂优先于负号)

result = (-2) ** 2
print(f'(-2) ** 2 = {result}')  # 4(括号改变了顺序)

5.2 详细优先级表

优先级运算符描述结合性
1(最高)()括号
2**幂运算右结合
3+x, -x, ~x一元正负号、按位取反右结合
4*, /, //, %乘、除、整除、取模左结合
5+, -加、减左结合

5.3 结合性:从左到右 vs 从右到左

# 左结合——从左到右计算(大多数运算符)
# 5 - 3 - 1 = (5 - 3) - 1 = 1
print(5 - 3 - 1)  # 1

# 5 / 2 / 2 = (5 / 2) / 2 = 1.25
print(5 / 2 / 2)  # 1.25

# 2 ** 3 ** 2 = 2 ** (3 ** 2) = 2 ** 9 = 512(右结合!)
print(2 ** 3 ** 2)  # 512

# 一元负号也是右结合
print(- - 5)  # 5 等价于 -(-5)

5.4 复杂的优先级示例

# 结合优先级和结合性,心算出以下表达式的结果

# 示例1
result = 10 + 5 * 2 ** 3 - 30 // 4
# 解析步骤:
# 10 + 5 * 8 - 30 // 4    (先算 2**3=8)
# 10 + 40 - 7              (5*8=40, 30//4=7)
# 43                      (10+40=50, 50-7=43)
print(f'10 + 5 * 2 ** 3 - 30 // 4 = {result}')  # 43

# 示例2
result = 25 // 3 % 2 * 4
# 解析步骤(同级左结合):
# 8 % 2 * 4              (25//3=8)
# 0 * 4                  (8%2=0)
# 0
print(f'25 // 3 % 2 * 4 = {result}')  # 0

# 示例3
result = -3 ** 2 + 10
# 解析步骤:
# -(3**2) + 10           (幂优先于负号)
# -9 + 10                (3**2=9)
# 1
print(f'-3 ** 2 + 10 = {result}')  # 1

# 示例4——注意浮点
result = 10 / 5 * 2
# 解析步骤(同级左结合):
# 2.0 * 2                (10/5=2.0)
# 4.0
print(f'10 / 5 * 2 = {result}')  # 4.0

# 示例5:嵌套幂运算
result = 2 ** 1 ** 3 ** 2
# 解析步骤(右结合):
# 2 ** (1 ** (3 ** 2))   (从最右边开始)
# 2 ** (1 ** 9)          (3**2=9)
# 2 ** 1                 (1**9=1)
# 2
print(f'2 ** 1 ** 3 ** 2 = {result}')  # 2

六、括号——最可靠的优先级控制工具

6.1 不确定时就加括号

# 即使你知道优先级规则,加括号也能让代码更易读
# 代码是写给人看的,不是写给编译器看的

# ❌ 代码能工作,但需要心算优先级
price = 100 * 0.8 + 5 * 2 + 10 / 2

# ✅ 加括号后一目了然
price = (100 * 0.8) + (5 * 2) + (10 / 2)

# ❌ 这个更难懂
flag = a < b and c > d or e == f

# ✅ 语义清晰
flag = (a < b and c > d) or (e == f)

# 经验法则:
# 1. 涉及3个以上不同优先级的运算符时——加括号
# 2. 涉及幂运算**时——加括号(右结合容易误解)
# 3. 负数参与运算时——加括号
# 4. 混合了算术和比较/逻辑运算符时——加括号

6.2 括号不影响性能

# 括号只影响编译时的解析,不影响运行时的性能
# 所以不要因为"性能"而不加括号——那是不存在的代价

import dis

def with_parens():
    return (a + b) * (c + d)

def without_parens():
    return a + b * c + d  # 和上面逻辑不同,但说明问题

# 括号在编译时就处理了,生成的字节码完全等价于不加括号的版本
# (当括号没有改变运算顺序时)

七、实际技巧和常见模式

7.1 快速计算技巧

# 判断奇偶
n = 7
if n % 2 == 0:
    print(f'{n}是偶数')
else:
    print(f'{n}是奇数')

# 快速除以2的幂
print(100 >> 1)  # 50(等价于100 // 2)
print(100 >> 2)  # 25(等价于100 // 4)
print(100 >> 3)  # 12(等价于100 // 8)

# 快速乘以2的幂
print(7 << 1)    # 14(等价于7 * 2)
print(7 << 2)    # 28(等价于7 * 4)
print(7 << 3)    # 56(等价于7 * 8)

# 限制数值范围
def clamp(value, min_val, max_val):
    """将数值限制在[min_val, max_val]范围内"""
    return max(min_val, min(value, max_val))

# 获取一个数的最后n位数字
num = 1234567
print(num % 100)      # 67(最后两位)
print(num % 1000)     # 567(最后三位)

# 去掉一个数的最后n位数字
print(num // 100)     # 12345(去掉最后两位)
print(num // 1000)    # 1234(去掉最后三位)

7.2 换算和单位转换

# 时间换算
def seconds_to_hms(total_seconds):
    """秒数转换为时:分:秒"""
    hours = total_seconds // 3600
    minutes = (total_seconds % 3600) // 60
    seconds = total_seconds % 60
    return f'{hours:02d}:{minutes:02d}:{seconds:02d}'

print(seconds_to_hms(3661))   # 01:01:01
print(seconds_to_hms(86399))  # 23:59:59

# 文件大小换算
def format_size(bytes_size):
    """字节数转换为可读的文件大小"""
    units = ['B', 'KB', 'MB', 'GB', 'TB']
    size = float(bytes_size)
    unit_index = 0
    
    while size >= 1024 and unit_index < len(units) - 1:
        size /= 1024
        unit_index += 1
    
    return f'{size:.2f} {units[unit_index]}'

print(format_size(1024))        # 1.00 KB
print(format_size(1048576))     # 1.00 MB
print(format_size(1234567890))  # 1.15 GB

7.3 循环和分页

# 分页计算
def paginate(items, page, per_page):
    """
    分页——计算总页数、当前页数据
    page: 页码(从1开始)
    per_page: 每页数量
    """
    total = len(items)
    total_pages = (total + per_page - 1) // per_page  # 向上取整
    
    start = (page - 1) * per_page
    end = min(start + per_page, total)
    
    return {
        'page': page,
        'per_page': per_page,
        'total': total,
        'total_pages': total_pages,
        'items': items[start:end],
        'has_next': page < total_pages,
        'has_prev': page > 1,
    }

# 示例
items = list(range(1, 26))  # 1到25
result = paginate(items, page=2, per_page=10)
print(f'第{result["page"]}页: {result["items"]}')  # [11, 12, ..., 20]
print(f'总页数: {result["total_pages"]}')          # 3
print(f'还有下一页: {result["has_next"]}')         # True

7.4 数学计算函数

import math

# Python内置的数学函数(不需要导入math)
print(abs(-10))          # 10(绝对值)
print(pow(2, 10))        # 1024(等价于2**10)
print(round(3.14159, 2)) # 3.14(四舍五入)
print(divmod(10, 3))     # (3, 1)——同时返回商和余数
# 等价于 (10 // 3, 10 % 3)

# math模块中的常用函数
print(math.sqrt(16))     # 4.0(平方根)
print(math.ceil(3.1))    # 4(向上取整)
print(math.floor(3.9))   # 3(向下取整)
print(math.trunc(-3.9))  # -3(向零取整——截断)
print(math.factorial(5)) # 120(阶乘)
print(math.gcd(12, 18))  # 6(最大公约数)
print(math.lcm(12, 18))  # 36(最小公倍数,Python 3.9+)
print(math.isclose(0.1+0.2, 0.3))  # True(浮点数近似相等比较)

八、综合实战:构建一个表达式计算器

把上面学到的知识串起来,自己动手写一个支持优先级和括号的简易计算器,会理解得更深。

class SimpleCalculator:
    """
    一个遵守Python运算符优先级规则的简单计算器。
    支持 +、-、*、/、//、%、** 和括号。
    """
    
    def __init__(self):
        self._operators = {
            '+': (1, lambda a, b: a + b),     # 优先级1(最低)
            '-': (1, lambda a, b: a - b),
            '*': (2, lambda a, b: a * b),     # 优先级2
            '/': (2, lambda a, b: a / b),
            '//': (2, lambda a, b: a // b),
            '%': (2, lambda a, b: a % b),
            '**': (3, lambda a, b: a ** b),   # 优先级3(最高)
        }
    
    def evaluate(self, expression):
        """
        使用双栈法(操作数栈+运算符栈)计算表达式。
        遵守Python的优先级和结合性规则。
        """
        tokens = self._tokenize(expression)
        return self._evaluate_tokens(tokens)
    
    def _tokenize(self, expression):
        """将表达式字符串分解为token列表"""
        tokens = []
        i = 0
        while i < len(expression):
            c = expression[i]
            
            # 跳过空格
            if c.isspace():
                i += 1
                continue
            
            # 数字(包括小数)
            if c.isdigit() or c == '.':
                j = i
                while j < len(expression) and (expression[j].isdigit() or expression[j] == '.'):
                    j += 1
                num_str = expression[i:j]
                tokens.append(float(num_str) if '.' in num_str else int(num_str))
                i = j
                continue
            
            # 括号
            if c in '()':
                tokens.append(c)
                i += 1
                continue
            
            # 运算符
            if c == '*' and i + 1 < len(expression) and expression[i + 1] == '*':
                tokens.append('**')
                i += 2
                continue
            if c == '/' and i + 1 < len(expression) and expression[i + 1] == '/':
                tokens.append('//')
                i += 2
                continue
            if c in '+-*/%':
                # 处理负号(前面是运算符或开头)
                if c == '-' and (i == 0 or expression[i-1] in '(+-*/%'):
                    pass  # 暂时不处理一元负号的情况
                tokens.append(c)
                i += 1
                continue
            
            i += 1
        
        return tokens
    
    def _evaluate_tokens(self, tokens):
        """计算token列表的值(简化版,支持+、-、*、/和括号)"""
        def apply_op(ops, vals):
            """应用栈顶的运算符"""
            if len(ops) == 0:
                return
            op = ops.pop()
            right = vals.pop()
            left = vals.pop()
            _, func = self._operators[op]
            vals.append(func(left, right))
        
        # 双栈算法
        ops = []   # 运算符栈
        vals = []  # 操作数栈
        
        for token in tokens:
            if isinstance(token, (int, float)):
                vals.append(token)
            elif token == '(':
                ops.append(token)
            elif token == ')':
                while ops and ops[-1] != '(':
                    apply_op(ops, vals)
                ops.pop()  # 弹出 '('
            elif token in self._operators:
                op_priority, _ = self._operators[token]
                # 处理运算符优先级
                while (ops and ops[-1] != '(' and 
                       ops[-1] in self._operators and
                       self._operators[ops[-1]][0] >= op_priority):
                    apply_op(ops, vals)
                ops.append(token)
        
        # 处理剩余运算符
        while ops:
            apply_op(ops, vals)
        
        return vals[0]


# 测试计算器
calc = SimpleCalculator()

print('=== 简单计算器测试 ===')
expressions = [
    '2 + 3 * 4',       # 14(乘法优先)
    '(2 + 3) * 4',     # 20(括号优先)
    '10 - 3 - 2',      # 5(左结合)
    '2 ** 3 + 1',      # 9(幂运算优先)
]

for expr in expressions:
    try:
        result = calc.evaluate(expr)
        python_result = eval(expr)
        print(f'{expr} = {result} (Python: {python_result})')
    except Exception as e:
        print(f'{expr} → 错误: {e}')

九、常见陷阱总结

9.1 陷阱一:整数除法和Python 2的区别

# Python 2: 3 / 2 = 1(整数除法)
# Python 3: 3 / 2 = 1.5(总是浮点数)

# 如果需要整数除法行为,用 //
print(3 // 2)    # 1

# 如果需要兼容Python 2的除法
# from __future__ import division  # 在Python 2中启用Python 3除法

9.2 陷阱二:取模的符号

# Python中,a % b的结果符号与b相同
print(10 % 3)     # 1  (正)
print(-10 % 3)    # 2  (正!与除数的符号一致)
print(10 % -3)    # -2 (负!与除数的符号一致)
print(-10 % -3)   # -1 (负!与除数的符号一致)

# 这和其他语言可能不同
# C/Ja va中:-10 % 3 = -1
# Python中:-10 % 3 = 2

# Python的设计遵循:a = b * (a // b) + (a % b)
# 验证恒等式
for a in [-10, -7, -3, 0, 3, 7, 10]:
    for b in [3, -3]:
        result = b * (a // b) + (a % b)
        assert result == a, f'恒等式失败: {a}, {b}'
print('恒等式验证通过 ✓')

9.3 陷阱三:幂运算的右结合和负号优先级

# ⚠️ 最常踩的坑:-2 ** 2
print(-2 ** 2)     # -4(不是4!)
print((-2) ** 2)   # 4

# ⚠️ 第二个坑:2 ** 3 ** 2
print(2 ** 3 ** 2)  # 512(不是64!)
print(2 ** (3 ** 2))  # 512
print((2 ** 3) ** 2)  # 64

# 建议:涉及**和负号时,永远加括号

9.4 陷阱四:浮点数比较

# ❌ 直接比较浮点数
a = 0.1 + 0.2
b = 0.3
print(a == b)  # False!

# ✅ 使用近似比较
import math
print(math.isclose(a, b))                      # True
print(math.isclose(a, b, rel_tol=1e-9))         # True

# ✅ 或者控制精度后比较
print(round(a, 10) == round(b, 10))             # True

# ✅ 最佳实践:使用Decimal进行精确小数计算
from decimal import Decimal
print(Decimal('0.1') + Decimal('0.2') == Decimal('0.3'))  # True

十、本篇小结

Python 的算术运算符看似简单,实则有不少值得留意的细节。下面用两个表格快速回顾核心内容。

七种算术运算符:

运算符名称示例备注
+10 + 3 = 13也用于字符串拼接
-10 - 3 = 7
*10 * 3 = 30也用于序列重复
/10 / 3 = 3.333...总是返回浮点数
//整除10 // 3 = 3向下取整
%取模10 % 3 = 1结果符号与除数一致
**10 ** 3 = 1000右结合

优先级口诀(从高到低):括号 → 幂(**) → 正负号(+x, -x) → 乘除模(* / // %) → 加减(+ -)

关键注意点:

  • /总是返回float,//才是整数除法(向下取整)
  • -2 ** 2 = -4(不是4)——幂优先于负号
  • 2 ** 3 ** 2 = 512(不是64)——幂是右结合
  • 0.1 + 0.2 ≠ 0.3——浮点数精度问题
  • 不确定优先级时——加括号

算术运算符是 Python 表达式的基础。下一篇我们将进入比较运算符的世界——==!=<><=>=,以及 Python 独有的链式比较特性。敬请期待!

本文内容来源于互联网,如有侵权请联系删除。
作者最新文章
编程开发 Python
相关文章 更多
Python安装后怎么打开:使用IDLE或命令行启动解释器
Python安装后怎么打开:使用IDLE或命令行启动解释器

刚在Windows安装好Python却不知道如何启动?本文详细演示如何通过开始菜单找到并打开IDLE集成开发环境,以及如何在PowerShell或命令提示符中使用python和py命令启动交互式解释器、运行.py脚本文件。包含退出解释器的方法及常见启动问题排查,帮助初学者快速验证安装成功并开始编写代码。

Windows系统Python安装教程:下载、勾选PATH及环境变量配置
Windows系统Python安装教程:下载、勾选PATH及环境变量配置

针对Windows初学者的Python安装实战指南。详细讲解如何从Python官网下载匹配架构的安装包,重点演示安装首屏勾选“Add python.exe to PATH”的关键操作,并提供使用python --version和py命令验证环境变量的具体步骤,帮助新手快速搭建开发环境并排查路径问题。

麒麟OS如何查看Python进程的运行状态
麒麟OS如何查看Python进程的运行状态

要想确认麒麟OS中Python程序的运行状态以及资源占用情况,我们可以这样做:用ps -ef | grep python来筛选进程;通过top命令,按P键排序查看实时负载;使用pgrep -f "script.py"精准获取PID;借助lsof -p PID验证文件打开状态。另外,还可以结合syst

Python在Debian上如何配置SSL证书
Python在Debian上如何配置SSL证书

在Debian系统上配置SSL证书通常涉及以下几个步骤:安装Web服务器:首先,你需要一个Web服务器,比如Apache或Nginx。这里以Apache为例。sudo apt updatesudo apt install apache2获取SSL证书:你可以从Let’s Encrypt免费获取SSL

统信UOS怎么安装Python开发环境
统信UOS怎么安装Python开发环境

要想让Python项目在统信UOS上正常运行,得先安装python3、python3-pip、python3-venv、python3-dev以及build-essential等组件。具体操作就是执行sudo apt install命令来一步到位完成安装,同时别忘了配置清华镜像源来给pip加速哦。在

纯Python方案实现中英文全文搜索
纯Python方案实现中英文全文搜索

在互联网上的各类网站中,无论大小,基本上都会有一个搜索框,用来给用户对内容进行搜索,小到站点搜索,大到搜索引擎搜索。从简单的来说,搜索功能确实很简单,一个简单的select语句就可以实现数据的搜索。而从复杂的来看,无论是搜索的精度还是搜索的效率,都是有很深的研究范围的。对于简单的搜索功能来说,一个s

Mac如何取消通过Python脚本运行的关机程序
Mac如何取消通过Python脚本运行的关机程序

立即在终端输入sudo shutdown -c取消倒计时关机,成功后显示“Shutdown cancelled”;若存在pmset重复任务,需再执行sudo pmset repeat cancel清除。Mac因Python脚本执行了os.system("sudo shutdown -h +10")或

Pythonasyncio异步并发与多固定出口IP调度实战
Pythonasyncio异步并发与多固定出口IP调度实战

之前写过一篇同步场景下用 Python 管理多个固定出口 IP 的实践(ExitPool + requests/httpx),覆盖了健康检查、故障转移和连接池复用。但在实际业务中,越来越多的场景用 asyncio 做高并发采集或批量接口调用——异步事件循环下多出口的管理方式和同步场景完全不同:单线程

Python在静态出口IP产品中的实战:从地址漂移巡检到多IP故障切换
Python在静态出口IP产品中的实战:从地址漂移巡检到多IP故障切换

写在前面:为什么静态出口 IP 不是"买了就行"不少团队在引入静态出口 IP 产品时,第一反应往往是:“地址配上去,这事就算完了。”可真到了真实业务里,静态出口 IP 真正能体现价值的地方,往往不在分配这一步,而在分配之后怎么管:地址有没有漂移,质量是否达标,某一条线路突然不可用时怎么切换,连接层又

using namespace 使用中遇到的问题怎么解决
using namespace 使用中遇到的问题怎么解决

命名空间的基本概念与常见引入问题在C++等编程语言中,命名空间(namespace)是一种将代码标识符(如变量、函数、类名)封装在特定名称下的机制,其主要目的是避免命名冲突,尤其是在大型项目或使用多个第三方库时。使用“using namespace”指令可以将指定命名空间中的所有名称引入当前作用域,

查看更多
精品专题 更多
装机必备
装机必备

正软商城装机必备专区,精选办公、浏览器、安全防护、影音播放、压缩解压、设计创作和系统工具等电脑常用正版软件,帮助用户快速完成新电脑软件配置。

Windows
Windows

正软商城Windows软件专区,汇集适用于Windows电脑的办公、设计、安全防护、影音播放、开发工具和系统优化软件,提供软件介绍、系统要求、正版授权及购买下载服务。

macOS软件
macOS软件

正软商城macOS软件专区,精选适用于Mac电脑的办公、设计、影音、效率、开发和系统工具,提供软件功能介绍、macOS兼容版本、正版授权及购买下载服务。

Mac软件 更多
灵活计算器
灵活计算器
macOS/iOS/Android

灵活计算器是一款笔记式算数应用,支持实时计算、动态关联和云端同步功能。记录、整理和输出之间的过渡会更自然,适合长期写作、做笔记或持续沉淀个人内容。

赤友清理大师
赤友清理大师
macOS

赤友清理大师是一款为 Mac 设计的智能清理优化工具,可精准扫描垃圾、大文件、重复文件等,释放磁盘空间。做扫描整理、文字提取和表格转换时,它能把识别后的处理步骤接得更顺,资料录入这类场景会省下不少时间。

极度公式
极度公式
Windows/macOS/Linux

极度公式是一款跨平台专业LaTeX公式识别编辑软件,支持OCR公式识别和多平台编辑。和使用说明,避免使用,享受完整功能与稳定支持。做扫描整理、文字提取和表格转换时,它能把识别后的处理步骤接得更顺,资料录入这类场景会省下不少时间。

WINDOWS 更多
Windows 10
Windows 10
Windows

Windows 10 是一款微软推出的经典操作系统,拥有硬件兼容性与多任务处理能力。它更偏向把系统状态查看和常用调节动作放在一起,适合需要持续观察和微调设备状态的场景。

极度公式
极度公式
Windows/macOS/Linux

极度公式是一款跨平台专业LaTeX公式识别编辑软件,支持OCR公式识别和多平台编辑。和使用说明,避免使用,享受完整功能与稳定支持。做扫描整理、文字提取和表格转换时,它能把识别后的处理步骤接得更顺,资料录入这类场景会省下不少时间。

密码键盘
密码键盘
Windows/macOS/iOS/Android

密码键盘是一款兼具安全性与便捷性的高效密码管理器。日常使用里的持续防护和信息管理会更突出,适合把安全控制放进长期使用流程中的场景。