如何在Python中覆盖浮点数列表的比较?
如何在Python中覆盖浮点数列表的比较?
我试图检查两个法向量是否相等。我的法向量表示为一个三元素列表,每个元素对应一个空间坐标(X、Y和Z)。所有坐标都保留四位小数。我想检查两个表面是否具有相同的法向量,所以我有以下代码:\n
if (surface1.normal in [surface2.normal, self.NegatedNormal(surface2.normal)]): # 在此处执行操作
\n问题是我的法向量看起来像这样:\n
surface1.normal: [0.9947, 0.0155, 0.1015] surface2.normal: [0.9947, 0.0155, 0.1014]
\n注意z坐标偏差0.0001。那么,有没有办法重写等号运算符,接受相互之间的答案在0.0001范围内,且与其他数据结构(例如列表)的比较兼容?我有一种感觉,我可能需要编写自己的__eq__方法,但是我不太确定如何做到这一点。\n另外,如果这不是最佳行动方案,是否有更好的方法来比较两个浮点数列表,给定一个容差范围?
如何在Python中覆盖浮点数列表的比较?
问题的原因是由于无法直接修改内置的List属性,但可以通过扩展自己的列表子类来覆盖它们。
以下是解决方法的代码示例:
class CustomList(list): deviation = None def deviation_check(self, val1, val2): if self.deviation: return min(val1, val2) + self.deviation >= max(val1, val2) return val1 == val2 def __eq__(self, other): is_equal = (self.deviation_check(self[0], other[0]) and self.deviation_check(self[1], other[1]) and self.deviation_check(self[2], other[2])) return is_equal l = CustomList() l.deviation = 0.0001 # 添加deviation作为属性 l.extend([0.9947, 0.0155, 0.1015]) l1 = CustomList() l1.extend([0.9947, 0.0155, 0.1014]) print l == l1
现在我们有两个CustomList对象l和l1,当您尝试检查列表的相等性`l == l1`时,Python会以以下方式检查其相等性:
`l.__eq__(l1)`
因此,我们重写了`__eq__`魔法方法,使其按照我们的期望工作。
如果您不添加`l.deviation`,它会检查相等性。此外,您必须清楚您要将`deviation`值添加到哪一边。
正如我之前所说的,`l == l1`在Python中被转换为`l.__eq__(l1)`,因此您必须将`deviation`属性添加到在`==`左边的列表对象上。
如果您运行上面的脚本,输出将是`True`。这是因为我们定义了`l.deviation == 0.0001`,这在检查相等性时产生了差异。
希望这解决了您的问题。
def __eq__(self, other): if len(self) != len(other): return False return all([self.deviation_check(item, other[index]) for index, item in enumerate(self)])
这将适用于任何长度的列表,而不仅仅是您上面的答案中适用于长度为3的列表。
您应该覆盖列表的构造函数以添加deviation参数。类似于`__init__(self, *args, deviation=1e-3)`,应使用适当的`super(CustomList, self).__init__(*args)`来允许您创建`CustomList(1,2,3,4,5, deviation=1e-6)`(未经测试,可能有错别字)。
在Python中,当比较浮点数列表中的元素时,可能会遇到比较不准确的问题。这可能是由于浮点数的精度问题导致的。为了解决这个问题,可以使用自定义函数来进行比较。
可以编写一个自定义函数来实现这个功能。例如:
def comp_floats(x, y, delta): return abs(x - y) < delta
在这个函数中,可以根据需要进行错误修正,这只是一个示例。
有人提出了一个更通用的解决方案,可以适用于其他编程逻辑。例如,原帖中的布尔值在某个公差范围内返回true,或者surface1.normal == surface2.normal返回true。基本上,我正在寻找一种重载比较运算符的好方法,但我不确定如何在Python中实现,或者根据我想要的效果是否可能。
在Python中,无法重写关键字/符号。所以以上提供的解决方案是可行的。
对于比较两个浮点数,我认为正确的方式应该是:
abs(x - y) < epsilon
谢谢,我总是记不住正确的算法。:P