在处理浮动列表/元组时,是否应避免使用 或而不是?它的实现类似于下面的代码还是更复杂的东西?
check = False
for item in list_to_search_the_value_in:
if value_to_search_for == item:
check = True
答案 0 :(得分:3)
in
和not in
应该是您首选的会员资格测试方式。两个运营商都可以使用(通过__contains__()
)容器提供的任何优化成员资格测试。
您的问题在于float
部分,因为in
与==
进行了相等比较(首先进行了优化以检查身份)。
一般来说,对于浮点比较,相等并不能产生预期的结果。因此,对于浮点数列表,您需要类似
的内容def is_in_float(item, sequence, eps=None):
eps = eps or 2**-52
return any((abs(item - seq_item) < eps) for seq_item in sequence)
与排序和二分查找一起使用,以便在您方便时找到最接近的匹配浮点数。
答案 1 :(得分:2)
Here's文档中说in
检查序列类型是否相等。所以不,这不应该用于浮动序列。
答案 2 :(得分:1)
__eq__()
运算符在后台使用常规的相等性检查,因此在浮点数时它与>>> 0.3 == 0.4 - 0.1
False
>>> 0.3 in [0.4 - 0.1]
False
具有相同的限制。如果有的话,请谨慎使用。
resources
答案 3 :(得分:1)
由于in
运算符使用了相等性检查,因此floating point math is "broken"(因为它不是,但是你得到了一点),它经常会失败。
使用any
:
epsilon = 1e-9
check = any(abs(f - value_to_search_for) < epsilon for f in seq)
# or
check = False
if any(abs(f - value_to_search_for) < epsilon for f in seq):
check = True
答案 4 :(得分:1)
Python的list
类型有__contains__
方法implemented in C:
static int
list_contains(PyListObject *a, PyObject *el)
{
Py_ssize_t i;
int cmp;
for (i = 0, cmp = 0 ; cmp == 0 && i < Py_SIZE(a); ++i)
cmp = PyObject_RichCompareBool(el, PyList_GET_ITEM(a, i),
Py_EQ);
return cmp;
}
Python的字面翻译可能是:
def list_contains(a, el):
cmp = False
for i in range(len(a)):
if cmp: break
cmp = a[i] == el
return cmp
您的例子是更惯用的翻译。
在任何情况下,正如其他答案所指出的那样,它使用相等来测试列表项与您正在检查成员身份的元素。对于float
值,这可能是危险的,因为我们期望相等的数字可能不是由于浮点舍入。
更多float
- 自己实施检查的安全方式可能是:
any(abs(x - el) < epsilon for x in a)
其中epsilon
是一个小值。它需要多小将取决于您正在处理的数字的大小,以及您需要多么精确。如果您可以估算可能区分el
列表中等效值的数字错误数量,则可以将epsilon
设置为一个数量级更大,并确信您不会给出误报(并且可能只在不可能正确的情况下给出误报)。