Python:列表中的Nan是否相等? [英] Python: equality for Nan in a list?

查看:168
本文介绍了Python:列表中的Nan是否相等?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我只想弄清楚这些结果背后的逻辑:

I just want to figure out the logic behind these results:

>>>nan = float('nan')
>>>nan == nan
False 
# I understand that this is because the __eq__ method is defined this way
>>>nan in [nan]
True 
# This is because the __contains__ method for list is defined to compare the identity first then the content?

但在这两种情况下,我都认为在幕后函数 PyObject_RichCompareBool 被称为对吗?为什么有区别?他们不应该有相同的行为吗?

But in both cases I think behind the scene the function PyObject_RichCompareBool is called right? Why there is a difference? Shouldn't they have the same behaviour?

推荐答案


但是在两种情况下,我都认为函数
PyObject_RichCompareBool 是正确的吗?为什么有区别?
是否应该具有相同的行为?

But in both cases I think behind the scene the function PyObject_RichCompareBool is called right? Why there is a difference? Shouldn't they have the same behaviour?

== 从不直接在float对象上调用 PyObject_RichCompareBool ,float具有自己的 rich_compare 方法(称为 __ eq __ )可能会也可能不会调用 PyObject_RichCompareBool ,具体取决于传递给它的参数。

== never calls PyObject_RichCompareBool on the float objects directly, floats have their own rich_compare method(called for __eq__) that may or may not call PyObject_RichCompareBool depending on the the arguments passed to it.

 /* Comparison is pretty much a nightmare.  When comparing float to float,
 * we do it as straightforwardly (and long-windedly) as conceivable, so
 * that, e.g., Python x == y delivers the same result as the platform
 * C x == y when x and/or y is a NaN.
 * When mixing float with an integer type, there's no good *uniform* approach.
 * Converting the double to an integer obviously doesn't work, since we
 * may lose info from fractional bits.  Converting the integer to a double
 * also has two failure modes:  (1) a long int may trigger overflow (too
 * large to fit in the dynamic range of a C double); (2) even a C long may have
 * more bits than fit in a C double (e.g., on a a 64-bit box long may have
 * 63 bits of precision, but a C double probably has only 53), and then
 * we can falsely claim equality when low-order integer bits are lost by
 * coercion to double.  So this part is painful too.
 */

static PyObject*
float_richcompare(PyObject *v, PyObject *w, int op)
{
    double i, j;
    int r = 0;

    assert(PyFloat_Check(v));
    i = PyFloat_AS_DOUBLE(v);

    /* Switch on the type of w.  Set i and j to doubles to be compared,
     * and op to the richcomp to use.
     */
    if (PyFloat_Check(w))
        j = PyFloat_AS_DOUBLE(w);

    else if (!Py_IS_FINITE(i)) {
        if (PyInt_Check(w) || PyLong_Check(w))
            /* If i is an infinity, its magnitude exceeds any
             * finite integer, so it doesn't matter which int we
             * compare i with.  If i is a NaN, similarly.
             */
            j = 0.0;
        else
            goto Unimplemented;
    }
...

另一方面, list_contains 直接在项目上调用 PyObject_RichCompareBool ,因此在第二种情况下您将获得True。

On the other hand the list_contains directly calls PyObject_RichCompareBool on the items hence you get True in the second case.

请注意,这仅适用于CPython,PyPy的 list .__ contains __ 方法似乎只是通过调用 __ eq __ 方法:

Note that this is true only for CPython, PyPy's list.__contains__ method only seems to be comparing the items by calling their __eq__ method:

$~/pypy-2.4.0-linux64/bin# ./pypy
Python 2.7.8 (f5dcc2477b97, Sep 18 2014, 11:33:30)
[PyPy 2.4.0 with GCC 4.6.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>>> nan = float('nan')
>>>> nan == nan
False
>>>> nan is nan
True
>>>> nan in [nan]
False

这篇关于Python:列表中的Nan是否相等?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆