"在"浮点数列表/元组的语句

时间:2016-06-03 11:32:34

标签: python

在处理浮动列表/元组时,是否应避免使用 而不是?它的实现类似于下面的代码还是更复杂的东西?

check = False
for item in list_to_search_the_value_in:
    if value_to_search_for == item:
        check = True

5 个答案:

答案 0 :(得分:3)

innot 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设置为一个数量级更大,并确信您不会给出误报(并且可能只在不可能正确的情况下给出误报)。