Python欧氏距离计算:closest_point函数结果不符问题求助
问题排查与修改方案
核心错误原因
你的closest_point函数使用字典存储距离-点映射,但字典的键具有唯一性:当多个点到中心点的距离相等时,后遍历到的点会覆盖先遍历到的点。在你的测试案例中:
- 中心点
Point(-30, 9)到Point(-19, 19)的距离平方为:(-30+19)² + (9-19)² = 121 + 100 = 221 - 到
Point(-20, 20)的距离平方同样为:(-30+20)² + (9-20)² = 100 + 121 = 221
两者距离完全相等,若Point(-20,20)在列表中晚于Point(-19,19)出现,字典会自动覆盖前者,导致返回错误结果。
此外,函数还存在两处冗余问题:
- 重复实现了欧几里得距离的计算逻辑,未复用已有的
euclidean_distance函数 - 找到最小距离后的
for循环完全多余,无需遍历字典即可直接返回结果
修改后的代码方案
方案1:保留原有距离计算逻辑,修复字典覆盖问题
直接遍历列表记录当前最近点,避免字典的键冲突问题:
import math class Point: """Defines the Point class for a 2D point. Data attributes: x - the x-coordinate of type float y - the y-coordinate of type float """ def __init__(self, x, y): """Creates a new Point object""" self.x = x self.y = y def __repr__(self): """A string representation of this Point""" return f"Point({self.x}, {self.y})" def euclidean_distance(point1, point2): """returns the euclidean distance between two points""" return math.sqrt((point1.x-point2.x) ** 2 + (point1.y-point2.y) **2) def closest_point(centre, points): """returns the nearest point in the list to the centre.""" if not points: return None # 处理空列表边界情况 # 初始化最近点为列表第一个元素 min_dist = euclidean_distance(centre, points[0]) closest = points[0] for point in points[1:]: current_dist = euclidean_distance(centre, point) # 仅当当前点距离更近时更新最近点,保留第一个出现的等距点 if current_dist < min_dist: min_dist = current_dist closest = point return closest
方案2:优化距离计算,使用平方距离提升效率
比较距离大小时,平方距离与实际距离的大小关系完全一致,无需开根号,可避免浮点运算的精度损耗并提升性能:
import math class Point: """Defines the Point class for a 2D point. Data attributes: x - the x-coordinate of type float y - the y-coordinate of type float """ def __init__(self, x, y): """Creates a new Point object""" self.x = x self.y = y def __repr__(self): """A string representation of this Point""" return f"Point({self.x}, {self.y})" def euclidean_distance(point1, point2): """returns the euclidean distance between two points""" return math.sqrt((point1.x-point2.x) ** 2 + (point1.y-point2.y) **2) def squared_distance(point1, point2): """returns squared euclidean distance for efficient comparison""" return (point1.x - point2.x) ** 2 + (point1.y - point2.y) ** 2 def closest_point(centre, points): """returns the nearest point in the list to the centre.""" if not points: return None min_sq_dist = squared_distance(centre, points[0]) closest = points[0] for point in points[1:]: current_sq_dist = squared_distance(centre, point) if current_sq_dist < min_sq_dist: min_sq_dist = current_sq_dist closest = point return closest
验证说明
修改后的函数会保留第一个出现的最近点,若你的测试列表中Point(-19,19)在Point(-20,20)之前,将返回预期结果。若需要保留最后一个出现的等距点,只需将if current_dist < min_dist改为if current_dist <= min_dist即可。
内容的提问来源于stack exchange,提问作者Nate Lee
相关产品推荐
相关产品推荐

