Python进阶教程:13_math 模块 —— 新手完全指南

一、什么是 math 模块?

1.1 一句话定义

math 是 Python 的内置数学库,提供了几乎所有常用的数学函数和常量(三角函数、对数、阶乘、取整、π、e 等)。

1.2 生活比喻

  • Python 内置运算+-*/**)= 你手上的计算器基本按键
  • math 模块 = 科学计算器上的所有高级按键(sin、cos、log、√、π...)

1.3 导入方式

python 复制代码
# 方式1:导入整个模块(推荐)
import math
print(math.pi)       # 3.141592653589793
print(math.sqrt(16)) # 4.0

# 方式2:导入特定函数
from math import sqrt, pi, sin
print(sqrt(16))  # 4.0
print(pi)        # 3.141592653589793

# 方式3:导入所有(不推荐,容易命名冲突)
from math import *

1.4 注意事项

python 复制代码
import math

# ⚠️ math 模块的函数只接受实数(int 或 float)
# 不支持复数!复数用 cmath 模块

math.sqrt(4)     # ✅ 2.0
math.sqrt(-4)    # ❌ ValueError: math domain error

# 如果需要复数运算:
import cmath
cmath.sqrt(-4)   # ✅ 2j

二、数学常量

python 复制代码
import math

# ============ π(圆周率) ============
print(math.pi)
# 3.141592653589793
# 用途:圆的周长、面积、三角函数等

# ============ e(自然常数) ============
print(math.e)
# 2.718281828459045
# 用途:自然对数、指数增长、复利计算等

# ============ τ(tau = 2π) ============
print(math.tau)
# 6.283185307179586
# 一个完整圆周 = τ 弧度(有些场景比 π 更直观)

# ============ 无穷大 ============
print(math.inf)       # inf(正无穷)
print(-math.inf)      # -inf(负无穷)
print(math.inf + 1)   # inf(无穷加任何数还是无穷)
print(math.inf > 999999999)  # True

# ============ NaN(非数字) ============
print(math.nan)       # nan
print(math.nan == math.nan)  # False!(NaN 不等于任何值,包括自己)
print(math.isnan(math.nan))  # True(用 isnan 判断)

# ============ 验证常量 ============
print(math.tau == 2 * math.pi)  # True

2.1 常量的实际应用

python 复制代码
import math

# 计算圆的面积和周长
radius = 5
area = math.pi * radius ** 2
circumference = 2 * math.pi * radius  # 或 math.tau * radius
print(f"半径={radius} 的圆:面积={area:.2f}, 周长={circumference:.2f}")
# 半径=5 的圆:面积=78.54, 周长=31.42

# 计算球体体积
def sphere_volume(r):
    return (4 / 3) * math.pi * r ** 3

print(f"半径=3 的球体积:{sphere_volume(3):.2f}")  # 113.10

# 角度转弧度
degrees = 180
radians = degrees * math.pi / 180  # 或 math.radians(degrees)
print(f"{degrees}° = {radians:.4f} 弧度")  # 180° = 3.1416 弧度

三、取整函数

3.1 ceil ------ 向上取整(天花板)

python 复制代码
import math

# ceil = ceiling(天花板),总是往"大"的方向取整
print(math.ceil(3.1))    # 4(往上到4)
print(math.ceil(3.9))    # 4
print(math.ceil(3.0))    # 3(已经是整数,不变)
print(math.ceil(-3.1))   # -3(-3 比 -3.1 大,所以是 -3)
print(math.ceil(-3.9))   # -3
print(math.ceil(0.001))  # 1

# 生活场景:
# 你有 23 个苹果,每箱装 5 个,需要几个箱子?
apples = 23
per_box = 5
boxes = math.ceil(apples / per_box)
print(f"需要 {boxes} 个箱子")  # 需要 5 个箱子(4箱装20个,第5箱装3个)

3.2 floor ------ 向下取整(地板)

python 复制代码
import math

# floor = 地板,总是往"小"的方向取整
print(math.floor(3.1))    # 3(往下到3)
print(math.floor(3.9))    # 3
print(math.floor(3.0))    # 3
print(math.floor(-3.1))   # -4(-4 比 -3.1 小,所以是 -4)
print(math.floor(-3.9))   # -4
print(math.floor(0.999))  # 0

# 生活场景:
# 你有 100 元,每个面包 7 元,最多买几个?
money = 100
price = 7
count = math.floor(money / price)
print(f"最多买 {count} 个面包")  # 最多买 14 个(14×7=98,剩2元)

# ⚠️ 注意:对正数,floor 等同于 int() 截断
print(math.floor(3.9))  # 3
print(int(3.9))         # 3(一样)

# 但对负数不同!
print(math.floor(-3.1))  # -4(往小取)
print(int(-3.1))         # -3(截断小数部分)

3.3 trunc ------ 截断(去掉小数部分)

python 复制代码
import math

# trunc = truncate(截断),直接砍掉小数部分(朝零方向)
print(math.trunc(3.9))    # 3
print(math.trunc(3.1))    # 3
print(math.trunc(-3.9))   # -3(朝零方向,不是 -4!)
print(math.trunc(-3.1))   # -3
print(math.trunc(0.999))  # 0

# 对比:
#          3.9   -3.9
# ceil:     4     -3   (往大)
# floor:    3     -4   (往小)
# trunc:    3     -3   (朝零)

# trunc 对正数等同于 floor,对负数等同于 ceil
# 实际上 int() 和 trunc() 效果一样
print(int(3.9))   # 3
print(int(-3.9))  # -3

3.4 取整对比图

python 复制代码
数轴:  -4   -3   -2   -1    0    1    2    3    4
         |    |    |    |    |    |    |    |    |

对于 3.7:
  floor(3.7) = 3  ←──┐
  trunc(3.7) = 3  ←──┤  (正数时相同)
  ceil(3.7)  = 4  ←──┘

对于 -3.7:
  floor(-3.7) = -4  ←──┐
  trunc(-3.7) = -3  ←──┤  (负数时不同!)
  ceil(-3.7)  = -3  ←──┘

3.5 其他取整相关

python 复制代码
import math

# ============ 判断是否为整数 ============
print(math.isfinite(3.14))     # True(是有限数)
print(math.isfinite(math.inf)) # False(无穷大不是有限数)
print(math.isfinite(math.nan)) # False

# ============ 判断是否为整数 ============
print(math.isinf(math.inf))    # True
print(math.isinf(100))         # False

print(math.isnan(math.nan))    # True
print(math.isnan(100))         # False

# ============ 判断是否为整数 ============
# Python 3.12+ 有 math.is_integer()(对 float)
# 通用方法:
x = 5.0
print(x == int(x))            # True(5.0 是整数)
y = 5.3
print(y == int(y))            # False(5.3 不是整数)

# 或者用 float.is_integer()
print((5.0).is_integer())     # True
print((5.3).is_integer())     # False

四、幂函数和对数函数

4.1 幂运算

python 复制代码
import math

# ============ pow(x, y):x 的 y 次方 ============
print(math.pow(2, 10))     # 1024.0(2^10)
print(math.pow(3, 3))      # 27.0(3^3)
print(math.pow(2, 0.5))    # 1.4142...(2的平方根)
print(math.pow(2, -1))     # 0.5(2的-1次方 = 1/2)

# ⚠️ math.pow 总是返回 float!
print(type(math.pow(2, 3)))  # <class 'float'>
print(type(2 ** 3))          # <class 'int'>(内置 ** 保持类型)

# 一般直接用 ** 更方便:
print(2 ** 10)   # 1024(int)
print(2 ** 0.5)  # 1.4142...(float)

# ============ sqrt(x):平方根 ============
print(math.sqrt(16))    # 4.0
print(math.sqrt(2))     # 1.4142135623730951
print(math.sqrt(0.25))  # 0.5
# math.sqrt(-1)  # ❌ ValueError(负数没有实数平方根)

# ============ cbrt(x):立方根(Python 3.11+) ============
print(math.cbrt(27))    # 3.0
print(math.cbrt(-8))    # -2.0(立方根可以是负数!)
print(math.cbrt(64))    # 4.0

# Python 3.11 之前用:
print((-8) ** (1/3))    # ❌ 复数!(1+1.732j)
print(math.copysign(abs(-8) ** (1/3), -8))  # ✅ -2.0

# ============ exp(x):e 的 x 次方 ============
print(math.exp(1))      # 2.718281828459045(就是 e)
print(math.exp(2))      # 7.38905609893065(e²)
print(math.exp(0))      # 1.0(e⁰ = 1)
print(math.exp(-1))     # 0.36787944117144233(e⁻¹ = 1/e)

# 对比:
print(math.exp(1) == math.e)  # True

# ============ expm1(x):e^x - 1(x很小时更精确) ============
# 当 x 非常小时,exp(x) - 1 会丢失精度
x = 1e-15
print(math.exp(x) - 1)      # 1.1102230246251565e-15(有误差)
print(math.expm1(x))         # 1e-15(精确!)

# 场景:计算极小的增长率
# 银行利率 0.0000000000001%,计算 e^r - 1
rate = 1e-15
print(math.expm1(rate))  # 精确结果

4.2 对数函数

python 复制代码
import math

# ============ log(x):自然对数(以 e 为底) ============
print(math.log(math.e))    # 1.0(ln(e) = 1)
print(math.log(1))         # 0.0(ln(1) = 0)
print(math.log(10))        # 2.302585092994046(ln(10))
print(math.log(math.e**3)) # 3.0(ln(e³) = 3)

# ============ log(x, base):以 base 为底的对数 ============
print(math.log(8, 2))      # 3.0(log₂(8) = 3,因为 2³=8)
print(math.log(100, 10))   # 2.0(log₁₀(100) = 2)
print(math.log(27, 3))     # 3.0(log₃(27) = 3)

# ============ log2(x):以 2 为底(比 log(x,2) 更精确) ============
print(math.log2(8))        # 3.0
print(math.log2(1024))     # 10.0
print(math.log2(0.5))      # -1.0

# 应用场景:计算二进制位数
n = 1000
bits = math.ceil(math.log2(n + 1))
print(f"表示 {n} 需要 {bits} 个二进制位")  # 需要 10 个二进制位

# ============ log10(x):以 10 为底(常用对数) ============
print(math.log10(100))     # 2.0
print(math.log10(1000))    # 3.0
print(math.log10(0.01))    # -2.0

# 应用场景:计算数字的位数
num = 123456
digits = math.floor(math.log10(num)) + 1
print(f"{num} 有 {digits} 位数")  # 123456 有 6 位数

# ============ log1p(x):ln(1+x)(x很小时更精确) ============
x = 1e-15
print(math.log(1 + x))     # 1.1102230246251565e-15(有误差)
print(math.log1p(x))       # 1e-15(精确!)

# 和 expm1 是互逆运算:
print(math.log1p(math.expm1(0.5)))  # 0.5(完美还原)

4.3 对数函数对照表

函数 含义 示例
math.log(x) ln(x),自然对数 log(e) → 1.0
math.log(x, base) log_base(x) log(8, 2) → 3.0
math.log2(x) log₂(x) log2(1024) → 10.0
math.log10(x) log₁₀(x) log10(1000) → 3.0
math.log1p(x) ln(1+x),小值精确 log1p(1e-15) → 1e-15
math.exp(x) exp(1) → 2.718...
math.expm1(x) eˣ - 1,小值精确 expm1(1e-15) → 1e-15

五、三角函数

5.1 角度与弧度

python 复制代码
import math

# ⚠️ 重要:math 的三角函数使用【弧度】,不是【角度】!
# 360° = 2π 弧度
# 180° = π 弧度
# 90°  = π/2 弧度
# 45°  = π/4 弧度

# ============ 角度 → 弧度 ============
print(math.radians(180))   # 3.141592653589793(= π)
print(math.radians(90))    # 1.5707963267948966(= π/2)
print(math.radians(45))    # 0.7853981633974483(= π/4)
print(math.radians(360))   # 6.283185307179586(= 2π = τ)

# ============ 弧度 → 角度 ============
print(math.degrees(math.pi))      # 180.0
print(math.degrees(math.pi / 2))  # 90.0
print(math.degrees(1.0))          # 57.29577951308232

# ============ 实用转换 ============
def sin_deg(degrees):
    """计算角度的正弦值(输入角度,不是弧度)"""
    return math.sin(math.radians(degrees))

def cos_deg(degrees):
    """计算角度的余弦值"""
    return math.cos(math.radians(degrees))

print(sin_deg(30))   # 0.49999999999999994(≈ 0.5)
print(cos_deg(60))   # 0.5000000000000001(≈ 0.5)
print(sin_deg(90))   # 1.0

5.2 基本三角函数

python 复制代码
import math

# ============ sin(x):正弦 ============
print(math.sin(0))              # 0.0
print(math.sin(math.pi / 6))    # 0.4999...(sin 30° ≈ 0.5)
print(math.sin(math.pi / 4))    # 0.7071...(sin 45° = √2/2)
print(math.sin(math.pi / 2))    # 1.0(sin 90° = 1)
print(math.sin(math.pi))        # 1.22e-16(≈ 0,浮点误差)

# ============ cos(x):余弦 ============
print(math.cos(0))              # 1.0(cos 0° = 1)
print(math.cos(math.pi / 3))    # 0.5000...(cos 60° = 0.5)
print(math.cos(math.pi / 2))    # 6.12e-17(≈ 0)
print(math.cos(math.pi))        # -1.0(cos 180° = -1)

# ============ tan(x):正切 ============
print(math.tan(0))              # 0.0
print(math.tan(math.pi / 4))    # 0.9999...(tan 45° ≈ 1)
print(math.tan(math.pi / 3))    # 1.7320...(tan 60° = √3)
# math.tan(math.pi / 2)  # 极大值(tan 90° 趋向无穷)

# ============ 特殊角度的值 ============
print("\n=== 特殊角度 ===")
angles = [0, 30, 45, 60, 90, 180, 270, 360]
print(f"{'角度':>6} {'sin':>10} {'cos':>10} {'tan':>10}")
print("-" * 40)
for deg in angles:
    rad = math.radians(deg)
    s = f"{math.sin(rad):.4f}"
    c = f"{math.cos(rad):.4f}"
    if deg in [90, 270]:
        t = "∞"
    else:
        t = f"{math.tan(rad):.4f}"
    print(f"{deg:>6}° {s:>10} {c:>10} {t:>10}")

输出

python 复制代码
=== 特殊角度 ===
  角度        sin        cos        tan
----------------------------------------
     0°     0.0000     1.0000     0.0000
    30°     0.5000     0.8660     0.5774
    45°     0.7071     0.7071     1.0000
    60°     0.8660     0.5000     1.7321
    90°     1.0000     0.0000          ∞
   180°     0.0000    -1.0000    -0.0000
   270°    -1.0000    -0.0000          ∞
   360°    -0.0000     1.0000    -0.0000

5.3 反三角函数

python 复制代码
import math

# 反三角函数:已知比值,求角度(返回弧度)

# ============ asin(x):反正弦 ============
# 已知 sin(θ) = x,求 θ
print(math.asin(0.5))              # 0.5236...(= π/6 = 30°)
print(math.asin(1.0))              # 1.5708...(= π/2 = 90°)
print(math.asin(0))                # 0.0
# math.asin(2)  # ❌ 值域是 [-1, 1]

# 转为角度:
print(math.degrees(math.asin(0.5)))  # 30.0°

# ============ acos(x):反余弦 ============
print(math.acos(0.5))              # 1.0472...(= π/3 = 60°)
print(math.acos(1.0))              # 0.0(cos 0° = 1)
print(math.acos(-1.0))             # 3.1416...(= π = 180°)
print(math.degrees(math.acos(0.5)))  # 60.0°

# ============ atan(x):反正切 ============
print(math.atan(1.0))              # 0.7854...(= π/4 = 45°)
print(math.atan(0))                # 0.0
print(math.degrees(math.atan(1)))  # 45.0°

# ============ atan2(y, x):反正切(考虑象限) ============
# atan2 比 atan 更好用!它能正确处理所有象限
# 返回点 (x, y) 与正 x 轴的夹角

print(math.atan2(1, 1))    # 0.785...(45°,第一象限)
print(math.atan2(1, -1))   # 2.356...(135°,第二象限)
print(math.atan2(-1, -1))  # -2.356...(-135°,第三象限)
print(math.atan2(-1, 1))   # -0.785...(-45°,第四象限)

# 对比 atan:
print(math.atan(1/1))      # 0.785(只能得到 -90°~90°)
print(math.atan(1/-1))     # -0.785(无法区分第二和第四象限!)

# 实际应用:计算两点之间的角度
def angle_between(x1, y1, x2, y2):
    """计算从点1到点2的方向角(度)"""
    dx = x2 - x1
    dy = y2 - y1
    angle_rad = math.atan2(dy, dx)
    return math.degrees(angle_rad)

print(angle_between(0, 0, 1, 1))    # 45.0°(右上方)
print(angle_between(0, 0, -1, 1))   # 135.0°(左上方)
print(angle_between(0, 0, 0, 1))    # 90.0°(正上方)
print(angle_between(0, 0, 1, 0))    # 0.0°(正右方)

5.4 双曲函数

python 复制代码
import math

# 双曲函数:和三角函数类似,但基于双曲线而非圆
# 在物理(悬链线)、工程中有应用

# ============ sinh(x):双曲正弦 ============
print(math.sinh(0))     # 0.0
print(math.sinh(1))     # 1.1752011936438014
print(math.sinh(-1))    # -1.1752011936438014(奇函数)

# ============ cosh(x):双曲余弦 ============
print(math.cosh(0))     # 1.0
print(math.cosh(1))     # 1.5430806348152437
print(math.cosh(-1))    # 1.5430806348152437(偶函数)

# ============ tanh(x):双曲正切 ============
print(math.tanh(0))     # 0.0
print(math.tanh(1))     # 0.7615941559557649
print(math.tanh(100))   # 1.0(趋近于1)
print(math.tanh(-100))  # -1.0(趋近于-1)

# 应用:tanh 常用作神经网络的激活函数
# 输出范围 (-1, 1),S 形曲线

# ============ 反双曲函数 ============
print(math.asinh(1.1752011936438014))  # ≈ 1.0
print(math.acosh(1.5430806348152437))  # ≈ 1.0
print(math.atanh(0.7615941559557649))  # ≈ 1.0

# ============ 悬链线方程 ============
# y = a * cosh(x/a) 描述悬挂的链条/电缆形状
def catenary(x, a=1):
    """悬链线方程"""
    return a * math.cosh(x / a)

# 打印悬链线
for x_int in range(-5, 6):
    x = x_int * 0.5
    y = catenary(x, a=2)
    bar = " " * int(y) + "●"
    print(f"x={x:5.1f} y={y:5.2f} {bar}")

六、特殊函数

6.1 阶乘

python 复制代码
import math

# ============ factorial(n):n 的阶乘 ============
print(math.factorial(0))   # 1(0! = 1,数学定义)
print(math.factorial(1))   # 1
print(math.factorial(5))   # 120(5×4×3×2×1)
print(math.factorial(10))  # 3628800
print(math.factorial(20))  # 2432902008176640000(Python 支持大整数!)

# ⚠️ 只接受非负整数
# math.factorial(-1)   # ❌ ValueError
# math.factorial(3.5)  # ❌ ValueError

# 应用:排列组合
# 5个人排成一排有多少种排法?
print(f"5人排列:{math.factorial(5)} 种")  # 120 种

# ============ comb(n, k):组合数 C(n,k)(Python 3.8+) ============
# 从 n 个中选 k 个(不考虑顺序)
print(math.comb(5, 2))    # 10(C(5,2) = 5!/(2!×3!) = 10)
print(math.comb(10, 3))   # 120
print(math.comb(52, 5))   # 2598960(扑克牌5张的组合数)

# ============ perm(n, k):排列数 P(n,k)(Python 3.8+) ============
# 从 n 个中选 k 个(考虑顺序)
print(math.perm(5, 2))    # 20(P(5,2) = 5!/(5-2)! = 5×4 = 20)
print(math.perm(10, 3))   # 720

# 对比:
# comb(5,2) = 10(选2人组队,不分先后)
# perm(5,2) = 20(选2人当正副班长,有先后)

# ============ 验证关系 ============
# P(n,k) = C(n,k) × k!
n, k = 10, 3
print(math.perm(n, k) == math.comb(n, k) * math.factorial(k))  # True

6.2 Gamma 函数

python 复制代码
import math

# ============ gamma(x):伽马函数 ============
# Γ(n) = (n-1)!(对正整数)
# 是阶乘在实数/复数上的推广

print(math.gamma(1))     # 1.0(= 0! = 1)
print(math.gamma(2))     # 1.0(= 1! = 1)
print(math.gamma(3))     # 2.0(= 2! = 2)
print(math.gamma(4))     # 6.0(= 3! = 6)
print(math.gamma(5))     # 24.0(= 4! = 24)
print(math.gamma(6))     # 120.0(= 5! = 120)

# 非整数值:
print(math.gamma(0.5))   # 1.7724538509055159(= √π)
print(math.gamma(1.5))   # 0.8862269254527579(= √π/2)

# ============ lgamma(x):ln|Γ(x)|(取对数,防止溢出) ============
# 当 n 很大时,n! 会溢出,但 ln(n!) 不会
print(math.lgamma(100))  # 359.134...(= ln(99!))
print(math.lgamma(1000)) # 5905.22...(= ln(999!))

# 对比:
# math.factorial(100) → 一个巨大的整数(Python 可以处理)
# 但在其他语言中会溢出,lgamma 是安全的选择

# 验证:lgamma(n+1) = ln(n!)
import math
n = 10
print(math.lgamma(n + 1))                    # 15.1044...
print(math.log(math.factorial(n)))           # 15.1044...(一样!)

6.3 误差函数

python 复制代码
import math

# ============ erf(x):误差函数 ============
# 在概率论和统计学中非常重要
# 与正态分布的累积分布函数相关

print(math.erf(0))       # 0.0
print(math.erf(1))       # 0.8427007929497149
print(math.erf(2))       # 0.9953222650189527
print(math.erf(-1))      # -0.8427...(奇函数)
print(math.erf(10))      # 1.0(趋近于1)

# ============ erfc(x):互补误差函数 = 1 - erf(x) ============
print(math.erfc(0))      # 1.0
print(math.erfc(1))      # 0.15729920705028513
# 当 x 很大时,erfc 比 1-erf 更精确

# 应用:计算正态分布概率
def normal_cdf(x, mu=0, sigma=1):
    """正态分布的累积分布函数"""
    z = (x - mu) / (sigma * math.sqrt(2))
    return 0.5 * (1 + math.erf(z))

# P(X ≤ 1.96) 在标准正态分布中
print(f"P(Z ≤ 1.96) = {normal_cdf(1.96):.4f}")  # ≈ 0.9750
print(f"P(Z ≤ 0) = {normal_cdf(0):.4f}")         # = 0.5000

七、浮点数操作

7.1 fabs ------ 绝对值(返回 float)

python 复制代码
import math

print(math.fabs(-3.14))   # 3.14
print(math.fabs(3.14))    # 3.14
print(math.fabs(0))       # 0.0
print(math.fabs(-0.0))    # 0.0

# 对比内置 abs():
print(abs(-3.14))    # 3.14(一样)
print(abs(-5))       # -5 → 5(返回 int)
print(math.fabs(-5)) # 5.0(总是返回 float)

7.2 copysign ------ 复制符号

python 复制代码
import math

# copysign(x, y):返回 x 的绝对值,但使用 y 的符号
print(math.copysign(5, -1))     # -5.0(5 的大小,-1 的符号)
print(math.copysign(-5, 1))     # 5.0(-5 的大小,1 的符号)
print(math.copysign(5, 1))      # 5.0
print(math.copysign(-5, -1))    # -5.0

# 应用:确保方向正确
speed = 10
direction = -1  # 向左
velocity = math.copysign(speed, direction)
print(f"速度:{velocity}")  # -10.0

7.3 fmod ------ 取余(浮点数)

python 复制代码
import math

# fmod 和 Python 的 % 对负数处理不同!
print(math.fmod(-7, 3))   # -1.0(结果的符号跟被除数一样)
print(-7 % 3)             # 2(Python 的 % 结果符号跟除数一样)

print(math.fmod(7, -3))   # 1.0
print(7 % -3)             # -2

# 对正数两者一样:
print(math.fmod(7, 3))    # 1.0
print(7 % 3)              # 1

# C 语言的 % 和 math.fmod 行为一致

7.4 fsum ------ 精确求和

python 复制代码
import math

# 普通 sum 有浮点误差:
numbers = [0.1] * 10
print(sum(numbers))        # 0.9999999999999999(不精确!)
print(math.fsum(numbers))  # 1.0(精确!)

# 更多例子:
print(sum([0.1, 0.2, 0.3]))        # 0.6000000000000001
print(math.fsum([0.1, 0.2, 0.3]))  # 0.6(精确)

# 原理:fsum 使用高精度中间累加,避免浮点误差累积
# 代价:比普通 sum 慢一些

# 适用场景:金融计算、科学计算等需要精确结果的场合
prices = [19.99, 5.01, 3.50, 7.25, 12.75]
print(f"普通求和:{sum(prices)}")       # 48.5(碰巧对了)
print(f"精确求和:{math.fsum(prices)}")  # 48.5

7.5 prod ------ 乘积(Python 3.8+)

python 复制代码
import math

# prod:计算所有元素的乘积
print(math.prod([1, 2, 3, 4, 5]))  # 120(1×2×3×4×5)
print(math.prod([2, 3, 4]))         # 24
print(math.prod([]))                # 1(空列表的乘积是1)
print(math.prod([5]))               # 5

# 可以指定初始值
print(math.prod([2, 3, 4], start=10))  # 240(10×2×3×4)

# 对比 reduce:
from functools import reduce
import operator
print(reduce(operator.mul, [1, 2, 3, 4, 5]))  # 120(一样)

7.6 gcd 和 lcm ------ 最大公约数和最小公倍数

python 复制代码
import math

# ============ gcd:最大公约数(Greatest Common Divisor) ============
print(math.gcd(12, 8))     # 4(12和8的最大公约数是4)
print(math.gcd(100, 75))   # 25
print(math.gcd(17, 13))    # 1(互质)
print(math.gcd(0, 5))      # 5

# 多个数(Python 3.9+)
print(math.gcd(12, 8, 6))  # 2

# 应用:化简分数
def simplify_fraction(numerator, denominator):
    """化简分数"""
    g = math.gcd(abs(numerator), abs(denominator))
    return numerator // g, denominator // g

print(simplify_fraction(12, 8))   # (3, 2) → 12/8 = 3/2
print(simplify_fraction(100, 75)) # (4, 3) → 100/75 = 4/3

# ============ lcm:最小公倍数(Least Common Multiple)(Python 3.9+) ============
print(math.lcm(4, 6))      # 12(4和6的最小公倍数是12)
print(math.lcm(3, 5))      # 15
print(math.lcm(12, 8))     # 24

# 多个数
print(math.lcm(2, 3, 4))   # 12

# 应用:计算周期
# 红灯每 30 秒变一次,绿灯每 45 秒变一次,多久同时变?
print(f"同时变化周期:{math.lcm(30, 45)} 秒")  # 90 秒

# 关系:lcm(a, b) × gcd(a, b) = a × b
a, b = 12, 8
print(math.lcm(a, b) * math.gcd(a, b) == a * b)  # True

7.7 isclose ------ 浮点数近似相等判断

python 复制代码
import math

# ⚠️ 浮点数不能直接用 == 比较!
print(0.1 + 0.2 == 0.3)           # False!(浮点误差)
print(0.1 + 0.2)                   # 0.30000000000000004

# ✅ 用 isclose 判断"近似相等"
print(math.isclose(0.1 + 0.2, 0.3))  # True!

# 参数:
# math.isclose(a, b, rel_tol=1e-09, abs_tol=0.0)
# rel_tol:相对容差(默认 1e-9,即十亿分之一)
# abs_tol:绝对容差(默认 0)

# 相对容差:|a-b| <= rel_tol * max(|a|, |b|)
print(math.isclose(1000000, 1000001, rel_tol=1e-5))  # True(差1,相对差很小)
print(math.isclose(1, 2, rel_tol=1e-5))              # False(差1,相对差很大)

# 绝对容差:适合比较接近 0 的数
print(math.isclose(1e-10, 2e-10, abs_tol=1e-9))  # True
print(math.isclose(1e-10, 2e-10))                 # False(默认容差太小)

# 实际应用:判断计算结果是否正确
result = math.sqrt(2) ** 2
print(math.isclose(result, 2.0))  # True(虽然可能有微小误差)

7.8 frexp 和 ldexp ------ 浮点数分解

python 复制代码
import math

# ============ frexp(x):分解为尾数和指数 ============
# x = mantissa × 2^exponent
# 其中 0.5 <= |mantissa| < 1

mantissa, exponent = math.frexp(8)
print(f"8 = {mantissa} × 2^{exponent}")  # 8 = 0.5 × 2^4
# 验证:0.5 × 16 = 8 ✓

mantissa, exponent = math.frexp(10)
print(f"10 = {mantissa} × 2^{exponent}")  # 10 = 0.625 × 2^4
# 验证:0.625 × 16 = 10 ✓

# ============ ldexp(x, i):frexp 的逆运算 ============
# 计算 x × 2^i
print(math.ldexp(0.5, 4))    # 8.0(0.5 × 2⁴ = 8)
print(math.ldexp(0.625, 4))  # 10.0(0.625 × 2⁴ = 10)

# 验证互逆:
x = 123.456
m, e = math.frexp(x)
print(math.ldexp(m, e))  # 123.456(还原!)

7.9 modf ------ 分离整数和小数部分

python 复制代码
import math

# modf(x):返回 (小数部分, 整数部分)
# ⚠️ 注意顺序:小数在前,整数在后!

frac, integ = math.modf(3.75)
print(f"小数部分:{frac}")   # 0.75
print(f"整数部分:{integ}")  # 3.0

frac, integ = math.modf(-3.75)
print(f"小数部分:{frac}")   # -0.75
print(f"整数部分:{integ}")  # -3.0

# 应用:分离时间和分钟
total_minutes = 137.5
frac, hours = math.modf(total_minutes / 60)
minutes = frac * 60
print(f"{total_minutes}分钟 = {int(hours)}小时{minutes:.0f}分钟")
# 137.5分钟 = 2小时17分钟(大约)

7.10 nextafter ------ 下一个浮点数(Python 3.9+)

python 复制代码
import math

# nextafter(x, y):从 x 朝 y 方向的下一个可表示的浮点数

# 比 1.0 大的最小浮点数
print(math.nextafter(1.0, 2.0))   # 1.0000000000000002
print(math.nextafter(1.0, 2.0) - 1.0)  # 2.220446049250313e-16(机器精度)

# 比 1.0 小的最大浮点数
print(math.nextafter(1.0, 0.0))   # 0.9999999999999999

# 比 0 大的最小正浮点数
print(math.nextafter(0.0, 1.0))   # 5e-324(极小!)

# 应用:测试边界条件
# 确保某个值严格大于 1.0
x = 1.0
x_strictly_greater = math.nextafter(x, math.inf)
print(x_strictly_greater > x)  # True

7.11 ulp ------ 最小精度单位(Python 3.9+)

python 复制代码
import math

# ulp = Unit in the Last Place(最后一位的单位)
# 表示浮点数的精度

print(math.ulp(1.0))     # 2.220446049250313e-16
print(math.ulp(1000.0))  # 1.1368683772161603e-13
print(math.ulp(0.0))     # 5e-324(最小正浮点数)

# 数越大,精度越低(ulp 越大)
print(math.ulp(1e100))   # 1.99584030953472e+84(精度很差了)

八、其他实用函数

8.1 degrees 和 radians

python 复制代码
import math

# 角度 ↔ 弧度 转换(前面已介绍,这里补充)

# 批量转换
angles_deg = [0, 30, 45, 60, 90, 120, 135, 150, 180]
angles_rad = [math.radians(d) for d in angles_deg]

print("角度 → 弧度:")
for d, r in zip(angles_deg, angles_rad):
    print(f"  {d:>3}° = {r:.4f} rad")

# 弧度 → 角度
rads = [0, math.pi/6, math.pi/4, math.pi/3, math.pi/2, math.pi]
degs = [math.degrees(r) for r in rads]
print("\n弧度 → 角度:")
for r, d in zip(rads, degs):
    print(f"  {r:.4f} rad = {d:.1f}°")

8.2 dist ------ 欧几里得距离(Python 3.8+)

python 复制代码
import math

# dist(p, q):计算两点之间的欧几里得距离
# 支持任意维度

# 2D 距离
p1 = (0, 0)
p2 = (3, 4)
print(math.dist(p1, p2))  # 5.0(经典的 3-4-5 直角三角形)

# 3D 距离
p1 = (0, 0, 0)
p2 = (1, 2, 2)
print(math.dist(p1, p2))  # 3.0(√(1+4+4) = √9 = 3)

# 高维距离
p1 = (1, 2, 3, 4, 5)
p2 = (5, 4, 3, 2, 1)
print(math.dist(p1, p2))  # 6.324...(√(16+4+0+4+16) = √40)

# 对比手动计算:
def manual_dist(p, q):
    return math.sqrt(sum((a - b) ** 2 for a, b in zip(p, q)))

print(manual_dist((0, 0), (3, 4)))  # 5.0(一样)

# 应用:计算地图上两点的直线距离(简化版)
def distance_km(lat1, lon1, lat2, lon2):
    """简化的距离计算(小范围近似)"""
    # 1度纬度 ≈ 111km
    # 1度经度 ≈ 111km × cos(纬度)
    dlat = (lat2 - lat1) * 111
    dlon = (lon2 - lon1) * 111 * math.cos(math.radians(lat1))
    return math.sqrt(dlat**2 + dlon**2)

# 北京(39.9, 116.4) 到 天津(39.1, 117.2)
d = distance_km(39.9, 116.4, 39.1, 117.2)
print(f"北京到天津约 {d:.1f} km")  # 约 120 km

8.3 hypot ------ 斜边/欧几里得范数

python 复制代码
import math

# hypot(x, y):计算 √(x² + y²)(直角三角形斜边)
# 比 sqrt(x**2 + y**2) 更不容易溢出

print(math.hypot(3, 4))     # 5.0(3-4-5 三角形)
print(math.hypot(5, 12))    # 13.0(5-12-13 三角形)
print(math.hypot(1, 1))     # 1.4142...(√2)

# Python 3.8+ 支持多维:
print(math.hypot(1, 2, 2))  # 3.0(√(1+4+4) = √9)
print(math.hypot(1, 2, 3, 4))  # 5.477...(√(1+4+9+16) = √30)

# 为什么用 hypot 而不是 sqrt(x**2 + y**2)?
# 当 x 或 y 极大时,x**2 可能溢出
big = 1e200
# math.sqrt(big**2 + big**2)  # ❌ OverflowError!
print(math.hypot(big, big))    # ✅ 1.4142e+200(正确处理)

# 应用:计算向量的长度(模)
def vector_length(x, y):
    return math.hypot(x, y)

print(f"向量(3,4)的长度:{vector_length(3, 4)}")  # 5.0

8.4 sumprod ------ 点积(Python 3.12+)

python 复制代码
import math

# sumprod(p, q):计算两个序列的点积(内积)
# 等价于 sum(a*b for a, b in zip(p, q))

print(math.sumprod([1, 2, 3], [4, 5, 6]))  # 32(1×4 + 2×5 + 3×6 = 32)
print(math.sumprod([1, 0, 1], [0, 1, 0]))  # 0(正交向量)

# Python 3.12 之前:
def dot_product(a, b):
    return sum(x * y for x, y in zip(a, b))

print(dot_product([1, 2, 3], [4, 5, 6]))  # 32

九、综合实战案例

9.1 几何计算工具

python 复制代码
import math

class Geometry:
    """几何计算工具类"""
    
    @staticmethod
    def circle_area(radius):
        """圆的面积"""
        return math.pi * radius ** 2
    
    @staticmethod
    def circle_circumference(radius):
        """圆的周长"""
        return math.tau * radius  # 2πr
    
    @staticmethod
    def triangle_area(a, b, c):
        """海伦公式:已知三边求面积"""
        s = (a + b + c) / 2  # 半周长
        return math.sqrt(s * (s - a) * (s - b) * (s - c))
    
    @staticmethod
    def triangle_area_sas(a, b, angle_deg):
        """已知两边及夹角求面积"""
        angle_rad = math.radians(angle_deg)
        return 0.5 * a * b * math.sin(angle_rad)
    
    @staticmethod
    def distance_2d(x1, y1, x2, y2):
        """两点距离"""
        return math.hypot(x2 - x1, y2 - y1)
    
    @staticmethod
    def angle_of_triangle(a, b, c):
        """余弦定理:已知三边求各角度(返回度)"""
        # cos(A) = (b² + c² - a²) / (2bc)
        cos_A = (b**2 + c**2 - a**2) / (2 * b * c)
        cos_B = (a**2 + c**2 - b**2) / (2 * a * c)
        cos_C = (a**2 + b**2 - c**2) / (2 * a * b)
        
        A = math.degrees(math.acos(cos_A))
        B = math.degrees(math.acos(cos_B))
        C = math.degrees(math.acos(cos_C))
        return A, B, C
    
    @staticmethod
    def regular_polygon_area(n, side_length):
        """正 n 边形面积"""
        return (n * side_length**2) / (4 * math.tan(math.pi / n))


# 使用
geo = Geometry()

print("=== 圆 ===")
r = 5
print(f"半径 {r}:面积 = {geo.circle_area(r):.2f}, 周长 = {geo.circle_circumference(r):.2f}")

print("\n=== 三角形(三边 3, 4, 5) ===")
a, b, c = 3, 4, 5
print(f"面积 = {geo.triangle_area(a, b, c):.2f}")
angles = geo.angle_of_triangle(a, b, c)
print(f"三个角 = {angles[0]:.1f}°, {angles[1]:.1f}°, {angles[2]:.1f}°")

print("\n=== 正六边形(边长 2) ===")
print(f"面积 = {geo.regular_polygon_area(6, 2):.2f}")

print("\n=== 两点距离 ===")
print(f"(0,0) 到 (3,4) = {geo.distance_2d(0, 0, 3, 4):.2f}")

9.2 物理计算

python 复制代码
import math

class Physics:
    """物理计算工具"""
    
    # 常量
    G = 6.674e-11       # 万有引力常数 (N⋅m²/kg²)
    g = 9.81            # 重力加速度 (m/s²)
    c = 3e8             # 光速 (m/s)
    
    @staticmethod
    def projectile_range(v0, angle_deg):
        """抛体运动的水平射程"""
        angle_rad = math.radians(angle_deg)
        return v0**2 * math.sin(2 * angle_rad) / Physics.g
    
    @staticmethod
    def projectile_max_height(v0, angle_deg):
        """抛体运动的最大高度"""
        angle_rad = math.radians(angle_deg)
        return v0**2 * math.sin(angle_rad)**2 / (2 * Physics.g)
    
    @staticmethod
    def projectile_time(v0, angle_deg):
        """抛体运动的飞行时间"""
        angle_rad = math.radians(angle_deg)
        return 2 * v0 * math.sin(angle_rad) / Physics.g
    
    @staticmethod
    def kinetic_energy(mass, velocity):
        """动能 E = ½mv²"""
        return 0.5 * mass * velocity**2
    
    @staticmethod
    def gravitational_force(m1, m2, r):
        """万有引力 F = Gm₁m₂/r²"""
        return Physics.G * m1 * m2 / r**2
    
    @staticmethod
    def pendulum_period(length):
        """单摆周期 T = 2π√(L/g)"""
        return 2 * math.pi * math.sqrt(length / Physics.g)
    
    @staticmethod
    def escape_velocity(mass, radius):
        """逃逸速度 v = √(2GM/R)"""
        return math.sqrt(2 * Physics.G * mass / radius)


# 使用
phy = Physics()

print("=== 抛体运动(初速度 50 m/s) ===")
for angle in [15, 30, 45, 60, 75]:
    r = phy.projectile_range(50, angle)
    h = phy.projectile_max_height(50, angle)
    t = phy.projectile_time(50, angle)
    print(f"  {angle:>2}°: 射程={r:.1f}m, 最大高度={h:.1f}m, 飞行时间={t:.2f}s")

print("\n=== 单摆周期 ===")
for L in [0.5, 1.0, 2.0, 4.0]:
    T = phy.pendulum_period(L)
    print(f"  摆长 {L}m: 周期 = {T:.3f}s")

print("\n=== 地球逃逸速度 ===")
M_earth = 5.972e24  # kg
R_earth = 6.371e6   # m
v_esc = phy.escape_velocity(M_earth, R_earth)
print(f"  逃逸速度 = {v_esc/1000:.2f} km/s")  # ≈ 11.19 km/s

9.3 金融计算

python 复制代码
import math

class Finance:
    """金融计算工具"""
    
    @staticmethod
    def compound_interest(principal, rate, years, n=12):
        """
        复利计算
        principal: 本金
        rate: 年利率(如 0.05 表示 5%)
        years: 年数
        n: 每年复利次数(12=月复利,365=日复利)
        """
        amount = principal * (1 + rate / n) ** (n * years)
        return amount
    
    @staticmethod
    def continuous_compound(principal, rate, years):
        """连续复利 A = P × e^(rt)"""
        return principal * math.exp(rate * years)
    
    @staticmethod
    def doubling_time(rate, n=12):
        """资金翻倍所需时间"""
        # (1 + r/n)^(nt) = 2
        # nt × ln(1 + r/n) = ln(2)
        # t = ln(2) / (n × ln(1 + r/n))
        return math.log(2) / (n * math.log1p(rate / n))
    
    @staticmethod
    def rule_of_72(rate_percent):
        """72法则:快速估算翻倍时间"""
        return 72 / rate_percent
    
    @staticmethod
    def present_value(future_value, rate, years):
        """现值计算(折现)"""
        return future_value / (1 + rate) ** years
    
    @staticmethod
    def loan_payment(principal, annual_rate, months):
        """等额本息月供"""
        r = annual_rate / 12  # 月利率
        if r == 0:
            return principal / months
        payment = principal * r * (1 + r)**months / ((1 + r)**months - 1)
        return payment


# 使用
fin = Finance()

print("=== 复利计算 ===")
P = 10000  # 本金 1 万
r = 0.05   # 年利率 5%
t = 10     # 10 年

print(f"本金 {P} 元,年利率 {r*100}%,{t} 年后:")
print(f"  年复利:{fin.compound_interest(P, r, t, n=1):.2f} 元")
print(f"  月复利:{fin.compound_interest(P, r, t, n=12):.2f} 元")
print(f"  日复利:{fin.compound_interest(P, r, t, n=365):.2f} 元")
print(f"  连续复利:{fin.continuous_compound(P, r, t):.2f} 元")

print(f"\n=== 翻倍时间(年利率 5%) ===")
exact = fin.doubling_time(0.05)
approx = fin.rule_of_72(5)
print(f"  精确计算:{exact:.2f} 年")
print(f"  72法则估算:{approx:.2f} 年")

print(f"\n=== 房贷月供 ===")
loan = 1000000  # 100万
rate = 0.042    # 年利率 4.2%
years = 30
monthly = fin.loan_payment(loan, rate, years * 12)
total = monthly * years * 12
interest = total - loan
print(f"  贷款 {loan/10000:.0f} 万,利率 {rate*100}%,{years} 年")
print(f"  月供:{monthly:.2f} 元")
print(f"  总还款:{total:.2f} 元")
print(f"  总利息:{interest:.2f} 元")

9.4 统计分析

python 复制代码
import math

class Statistics:
    """基础统计工具"""
    
    @staticmethod
    def mean(data):
        """算术平均值"""
        return math.fsum(data) / len(data)
    
    @staticmethod
    def geometric_mean(data):
        """几何平均值"""
        # GM = (x1 × x2 × ... × xn)^(1/n)
        # 用对数避免溢出:GM = exp(mean(ln(xi)))
        log_sum = math.fsum(math.log(x) for x in data)
        return math.exp(log_sum / len(data))
    
    @staticmethod
    def harmonic_mean(data):
        """调和平均值"""
        # HM = n / (1/x1 + 1/x2 + ... + 1/xn)
        return len(data) / math.fsum(1/x for x in data)
    
    @staticmethod
    def variance(data):
        """方差"""
        m = Statistics.mean(data)
        return math.fsum((x - m) ** 2 for x in data) / len(data)
    
    @staticmethod
    def std_dev(data):
        """标准差"""
        return math.sqrt(Statistics.variance(data))
    
    @staticmethod
    def rms(data):
        """均方根(Root Mean Square)"""
        return math.sqrt(math.fsum(x**2 for x in data) / len(data))


# 使用
stats = Statistics()

data = [2, 4, 4, 4, 5, 5, 7, 9]

print(f"数据:{data}")
print(f"算术平均:{stats.mean(data):.2f}")
print(f"几何平均:{stats.geometric_mean(data):.2f}")
print(f"调和平均:{stats.harmonic_mean(data):.2f}")
print(f"方差:{stats.variance(data):.2f}")
print(f"标准差:{stats.std_dev(data):.2f}")
print(f"均方根:{stats.rms(data):.2f}")

# 三种平均数的关系:调和 ≤ 几何 ≤ 算术
print(f"\n验证:{stats.harmonic_mean(data):.4f} ≤ {stats.geometric_mean(data):.4f} ≤ {stats.mean(data):.4f}")

# 应用:计算平均速度
# 去程 60km/h,回程 40km/h,平均速度是多少?
# 不是 (60+40)/2 = 50!应该用调和平均
speeds = [60, 40]
print(f"\n去程60,回程40,平均速度 = {stats.harmonic_mean(speeds):.1f} km/h")
# 48.0 km/h(不是50!)

十、math 模块完整函数速查表

python 复制代码
═══════════════════════════════════════════════════════
  常量
═══════════════════════════════════════════════════════
  math.pi        圆周率 π = 3.14159...
  math.e         自然常数 e = 2.71828...
  math.tau       τ = 2π = 6.28318...
  math.inf       正无穷
  math.nan       非数字

═══════════════════════════════════════════════════════
  取整
═══════════════════════════════════════════════════════
  ceil(x)        向上取整(天花板)
  floor(x)       向下取整(地板)
  trunc(x)       截断(朝零方向)

═══════════════════════════════════════════════════════
  幂和对数
═══════════════════════════════════════════════════════
  pow(x, y)      x^y(返回float)
  sqrt(x)        平方根 √x
  cbrt(x)        立方根(3.11+)
  exp(x)         e^x
  expm1(x)       e^x - 1(小值精确)
  log(x)         自然对数 ln(x)
  log(x, base)   以 base 为底
  log2(x)        以 2 为底
  log10(x)       以 10 为底
  log1p(x)       ln(1+x)(小值精确)

═══════════════════════════════════════════════════════
  三角函数(参数为弧度)
═══════════════════════════════════════════════════════
  sin(x)         正弦
  cos(x)         余弦
  tan(x)         正切
  asin(x)        反正弦
  acos(x)        反余弦
  atan(x)        反正切
  atan2(y, x)    反正切(考虑象限)

═══════════════════════════════════════════════════════
  双曲函数
═══════════════════════════════════════════════════════
  sinh(x)        双曲正弦
  cosh(x)        双曲余弦
  tanh(x)        双曲正切
  asinh(x)       反双曲正弦
  acosh(x)       反双曲余弦
  atanh(x)       反双曲正切

═══════════════════════════════════════════════════════
  角度转换
═══════════════════════════════════════════════════════
  degrees(x)     弧度 → 角度
  radians(x)     角度 → 弧度

═══════════════════════════════════════════════════════
  特殊函数
═══════════════════════════════════════════════════════
  factorial(n)   阶乘 n!
  comb(n, k)     组合数 C(n,k)(3.8+)
  perm(n, k)     排列数 P(n,k)(3.8+)
  gamma(x)       伽马函数 Γ(x)
  lgamma(x)      ln|Γ(x)|
  erf(x)         误差函数
  erfc(x)        互补误差函数

═══════════════════════════════════════════════════════
  浮点操作
═══════════════════════════════════════════════════════
  fabs(x)        绝对值(返回float)
  copysign(x,y)  复制符号
  fmod(x, y)     取余(C风格)
  fsum(iterable) 精确求和
  prod(iterable) 乘积(3.8+)
  gcd(a, b)      最大公约数
  lcm(a, b)      最小公倍数(3.9+)
  isclose(a, b)  近似相等判断
  frexp(x)       分解为尾数×2^指数
  ldexp(x, i)    x × 2^i
  modf(x)        分离整数和小数
  nextafter(x,y) 下一个浮点数(3.9+)
  ulp(x)         最小精度单位(3.9+)

═══════════════════════════════════════════════════════
  其他
═══════════════════════════════════════════════════════
  hypot(x, y)    斜边 √(x²+y²)
  dist(p, q)     欧几里得距离(3.8+)
  sumprod(p, q)  点积(3.12+)
  isfinite(x)    是否有限
  isinf(x)       是否无穷
  isnan(x)       是否NaN

十一、常见错误和注意事项

11.1 浮点精度问题

python 复制代码
import math

# ❌ 不要用 == 比较浮点数
print(math.sin(math.pi) == 0)  # False!(结果是 1.22e-16)

# ✅ 用 isclose
print(math.isclose(math.sin(math.pi), 0, abs_tol=1e-10))  # True

# ❌ 不要期望精确结果
print(math.sqrt(2) ** 2)  # 2.0000000000000004(不是精确的2)

# ✅ 用 isclose
print(math.isclose(math.sqrt(2) ** 2, 2.0))  # True

11.2 定义域错误

python 复制代码
import math

# 以下都会报错:
# math.sqrt(-1)      # ValueError: math domain error
# math.log(0)        # ValueError: math domain error
# math.log(-1)       # ValueError: math domain error
# math.asin(2)       # ValueError(值域是[-1,1])
# math.acos(2)       # ValueError
# math.factorial(-1) # ValueError
# math.factorial(3.5)# ValueError

# 安全写法:
def safe_sqrt(x):
    if x < 0:
        return None  # 或 raise ValueError
    return math.sqrt(x)

def safe_log(x):
    if x <= 0:
        return None
    return math.log(x)

11.3 math vs 内置函数

python 复制代码
import math

# 有些功能 math 和内置都有,区别:
print(abs(-5))        # 5(int)
print(math.fabs(-5))  # 5.0(总是 float)

print(2 ** 10)        # 1024(int,精确)
print(math.pow(2, 10))# 1024.0(float)

print(sum([0.1]*10))        # 0.9999...(有误差)
print(math.fsum([0.1]*10))  # 1.0(精确)

# 建议:
# 整数幂 → 用 **
# 浮点幂 → 用 math.pow 或 **
# 精确求和 → 用 math.fsum
# 普通求和 → 用 sum(更快)

十二、学习路径建议

python 复制代码
第1天:常量(pi, e)+ 取整(ceil, floor, trunc)
第2天:幂和对数(sqrt, pow, log, exp)
第3天:三角函数(sin, cos, tan + 角度转换)
第4天:特殊函数(factorial, gcd, comb)
第5天:浮点操作(isclose, fsum, hypot)
第6天:综合练习(几何、物理、金融计算)
第7天:了解 cmath(复数版本)和 numpy(数组版本)

十三、一句话总结

math 模块 = Python 的科学计算器

记住三个关键点:

  1. 三角函数用弧度 (用 math.radians() 转换)
  2. 浮点数比较用 math.isclose() (不要用 ==
  3. 精确求和用 math.fsum() (不要用 sum()
相关推荐
__zRainy__1 小时前
Node系列 · 数据库:单表查询
数据库·后端·mysql·node.js
xcLeigh1 小时前
聊聊数据库迁移工具怎么从单机走向“云+端+服务”,KDMS架构拆解
数据库·架构·数据库迁移·kes·kdms·架构拆解
学学酱快乐1 小时前
2026年PMP考试生命周期选择决策树精讲:从需求判断到混合型统一框架的应试全攻略
算法·决策树·机器学习·pmp新版考试大纲·pmp新题型·pmp培训哪家好·pmp培训机构推荐
aiqianji1 小时前
教AI短篇小说写作的软件操作简单,该怎么挑选呢?
人工智能·python
St_rive1 小时前
selenium cookie的处理
数据库·selenium·测试工具
Rocky Ding*2 小时前
【三年面试五年模拟】2026-08-18_哔哩哔哩AI应用岗Agent开发一面面经全解析(含完整答案)
论文阅读·人工智能·深度学习·机器学习·aigc·ai-native·ai agent
circuitsosk2 小时前
Python 模块与包管理:import 机制、虚拟环境与 pip 完全指南
开发语言·python·pip·依赖管理·模块与包
weixin_440730502 小时前
python+request实现接口-小结
开发语言·python