【数学笔记】常见距离计算:欧氏、曼哈顿、切比雪夫
【数学笔记】常见距离计算:欧氏、曼哈顿、切比雪夫
2022-07-01 / 0 评论 / 180 阅读 / 60 点赞

【数学笔记】常见距离计算:欧氏、曼哈顿、切比雪夫

发光的神
2022-07-01 / 0 评论 / 180 阅读 / 正在检测是否收录...

简介

在数据分析、路径规划、机器学习这些场景里,经常要算两个点/向量之间的“距离”,欧氏、曼哈顿、切比雪夫是最基础也最常用的三种,我结合公式和Python代码把它们捋清楚,记下来方便后续用,尽量写得直白,重点在“能看懂、能复用”。

1. 欧氏距离(Euclidean Distance)

核心说明

欧式距离就是咱们最直观的“直线距离”,比如平面上两点间的直线长度,三维空间里两点间的直线长度,本质是勾股定理的延伸,也是最符合日常认知的距离计算方式。

公式

(1) 二维平面上两点 $a(x_1, y_1)$ 和 $b(x_2,y_2)$ 的直线距离:
$d(a,b) = \sqrt{(x_2 - x_1)^2 + (y_2 - y_1)^2}$

(2) 三维空间两点 $a(x_1,y_1,z_1)$、$b(x_2,y_2,z_2)$ 间的欧氏距离:
$d(a,b) = \sqrt{(x_2 - x_1)^2 + (y_2 - y_1)^2 + (z_2 - z_1)^2}$

(3) 两个n维向量 $a(x_{11},x_{12},\dots,x_{1n})$ 和 $b(x_{21},x_{22},\dots,x_{2n})$ 间的欧氏距离:
$d(a,b) = \sqrt{\sum_{i=1}^n (x_{2i} - x_{1i})^2}$

也可以表示成向量运算的形式:
$d(a,b) = \sqrt{(a - b)^T(a - b)}$

Python实现(支持n维向量)

import math

def euclidean_distance(a, b):
    """
    计算两个n维向量的欧氏距离
    :param a: 第一个向量(列表/元组,如[1,50.6]、[1,2,3])
    :param b: 第二个向量(维度需和a一致)
    :return: 欧氏距离值
    """
    if len(a) != len(b):
        raise ValueError("两个向量的维度必须一致!")
    # 先算每个维度差值的平方和,再开平方
    squared_sum = sum((x - y)**2 for x, y in zip(a, b))
    return math.sqrt(squared_sum)

# 测试案例
# 二维案例(原示例)
test_a_2d = [1, 50.6]
test_b_2d = [1, 1]
print(f"二维欧氏距离:{euclidean_distance(test_a_2d, test_b_2d)}") # 输出49.6

# 三维案例
test_a_3d = [1, 2, 3]
test_b_3d = [4, 5, 6]
print(f"三维欧氏距离:{euclidean_distance(test_a_3d, test_b_3d)}") # 输出√(9+9+9)=√27≈5.196

2. 曼哈顿距离(Manhattan Distance)

核心说明

曼哈顿距离也叫“城市街区距离”,不是直线距离,而是像在城市里走路一样,只能沿横竖方向走,算的是“横向+纵向”的总路程,比如从A点到B点,绕着街区走的总距离。

公式

(1) 二维平面两点 $a(x_1,y_1)$ 和 $b(x_2,y_2)$ 间的曼哈顿距离:
$d(a,b) = |x_2 - x_1| + |y_2 - y_1|$

(2) 两个n维向量 $a(x_{11},x_{12},\dots,x_{1n})$ 与 $b(x_{21},x_{22},\dots,x_{2n})$ 间的曼哈顿距离:
$d(a,b) = \sum_{i=1}^n |x_{2i} - x_{1i}|$

Python实现(支持n维向量)

def manhattan_distance(a, b):
    """
    计算两个n维向量的曼哈顿距离
    :param a: 第一个向量(列表/元组)
    :param b: 第二个向量(维度需和a一致)
    :return: 曼哈顿距离值
    """
    if len(a) != len(b):
        raise ValueError("两个向量的维度必须一致!")
    # 累加每个维度差值的绝对值
    return sum(abs(x - y) for x, y in zip(a, b))

# 测试案例
# 二维案例(原示例)
print(f"二维曼哈顿距离:{manhattan_distance(test_a_2d, test_b_2d)}") # 输出0 + 49.6 = 49.6

# 三维案例
print(f"三维曼哈顿距离:{manhattan_distance(test_a_3d, test_b_3d)}") # 输出3+3+3=9

3. 切比雪夫距离(Chebyshev Distance)

核心说明

切比雪夫距离可以理解成“国王距离”——国际象棋里国王走一步能到相邻8个方格中的任意一个,从A点到B点,国王最少需要走的步数就是切比雪夫距离,本质是两个点各维度差值的绝对值中最大的那个。

公式

(1) 二维平面两点 $a(x_1,y_1)$ 和 $b(x_2,y_2)$ 间的切比雪夫距离:
$d(a,b) = \max(|x_2 - x_1|, |y_2 - y_1|)$

(2) 两个n维向量 $a(x_{11},x_{12},\dots,x_{1n})$ 和 $b(x_{21},x_{22},\dots,x_{2n})$ 间的切比雪夫距离:
$d(a,b) = \max_{i=1}^n |x_{2i} - x_{1i}|$

Python实现(支持n维向量)

def chebyshev_distance(a, b):
    """
    计算两个n维向量的切比雪夫距离
    :param a: 第一个向量(列表/元组)
    :param b: 第二个向量(维度需和a一致)
    :return: 切比雪夫距离值
    """
    if len(a) != len(b):
        raise ValueError("两个向量的维度必须一致!")
    # 取每个维度差值绝对值的最大值
    return max(abs(x - y) for x, y in zip(a, b))

# 测试案例
# 二维案例(棋盘场景)
chess_a = (1, 1)
chess_b = (5, 4)
print(f"棋盘上国王从{chess_a}到{chess_b}的步数(切比雪夫距离):{chebyshev_distance(chess_a, chess_b)}") # 差值x=4,y=3,最大值4,输出4

# 原示例二维测试
print(f"原示例切比雪夫距离:{chebyshev_distance(test_a_2d, test_b_2d)}") # 差值x=0,y=49.6,最大值49.6,输出49.6

# 三维案例
print(f"三维切比雪夫距离:{chebyshev_distance(test_a_3d, test_b_3d)}") # 差值都是3,最大值3,输出3

4. 三种距离的整合调用

整合代码

def calculate_distance(a, b, distance_type="euclidean"):
    """
    统一计算三种距离的封装函数
    :param a: 第一个向量
    :param b: 第二个向量
    :param distance_type: 距离类型,可选"euclidean"/"manhattan"/"chebyshev"
    :return: 对应类型的距离值
    """
    if len(a) != len(b):
        raise ValueError("两个向量维度必须一致!")
    
    if distance_type == "euclidean":
        return euclidean_distance(a, b)
    elif distance_type == "manhattan":
        return manhattan_distance(a, b)
    elif distance_type == "chebyshev":
        return chebyshev_distance(a, b)
    else:
        raise ValueError("距离类型仅支持euclidean/manhattan/chebyshev!")

# 批量测试
test_vec1 = [2, 5, 8]
test_vec2 = [6, 9, 12]
print(f"批量测试 - 欧氏距离:{calculate_distance(test_vec1, test_vec2, 'euclidean')}") # √(16+16+16)=√48≈6.928
print(f"批量测试 - 曼哈顿距离:{calculate_distance(test_vec1, test_vec2, 'manhattan')}") # 4+4+4=12
print(f"批量测试 - 切比雪夫距离:{calculate_distance(test_vec1, test_vec2, 'chebyshev')}") # 最大值4

闵可夫斯基距离(三种统一)

其实欧氏、曼哈顿、切比雪夫都是“闵可夫斯基距离”的特例,公式如下:
$d(a,b) = \left( \sum_{i=1}^n |x_{2i} - x_{1i}|^p \right)^{\frac{1}{p}}$

  • 当 $p=1$ 时,就是曼哈顿距离
  • 当 $p=2$ 时,就是欧氏距离
  • 当 $p \to \infty$ 时,就是切比雪夫距离
def minkowski_distance(a, b, p):
    """
    计算闵可夫斯基距离(p为参数,覆盖三种基础距离)
    :param a: 第一个向量
    :param b: 第二个向量
    :param p: 阶数(p=1→曼哈顿,p=2→欧氏,p越大越接近切比雪夫)
    :return: 闵可夫斯基距离值
    """
    if len(a) != len(b):
        raise ValueError("两个向量维度必须一致!")
    if p <= 0:
        raise ValueError("p必须大于0!")
    
    # p→∞时直接返回切比雪夫距离(简化版)
    if p == float("inf"):
        return chebyshev_distance(a, b)
    
    sum_pow = sum(abs(x - y)**p for x, y in zip(a, b))
    return sum_pow ** (1/p)

# 验证特例
print(f"p=1(曼哈顿):{minkowski_distance(test_vec1, test_vec2, 1)}") # 12,和之前一致
print(f"p=2(欧氏):{minkowski_distance(test_vec1, test_vec2, 2)}") # ≈6.928,和之前一致
print(f"p=∞(切比雪夫):{minkowski_distance(test_vec1, test_vec2, float('inf'))}") # 4,和之前一致

5. 三种应用场景

距离类型核心特点典型应用场景
欧氏距离直线距离,贴合直观认知机器学习(相似度计算、KNN算法)、坐标定位、三维建模
曼哈顿距离街区式路程,对异常值更稳健路径规划(外卖配送、城市导航)、推荐系统(用户行为相似度)
切比雪夫距离最大维度差值,“步数”思维棋盘类算法、物流配送(最大运输维度优化)、多维度决策

总结

  1. 欧氏、曼哈顿、切比雪夫是最基础的距离计算方式,核心区别在于“维度差值的处理方式”(平方和开方/绝对值和/绝对值最大值);
  2. 三种距离都能扩展到n维向量,代码实现时要注意“维度一致”的校验,避免报错;
  3. 闵可夫斯基距离是三者的统一形式,通过调整参数p可以切换不同距离类型,方便灵活调用;
  4. 实际使用时要根据场景选:要直线距离选欧氏,要路径总长度选曼哈顿,要“最少步数”选切比雪夫。
60

评论 (0)

取消
0:00