Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python NaN';集合中的s与唯一性_Python_Python 3.x_Set_Nan_Ieee 754 - Fatal编程技术网

Python NaN';集合中的s与唯一性

Python NaN';集合中的s与唯一性,python,python-3.x,set,nan,ieee-754,Python,Python 3.x,Set,Nan,Ieee 754,我刚刚偶然发现了Python的这一有趣行为,它涉及sets中的NaN: #测试1 nan=浮点('nan') 事物=[0,1,2,nan,'a',1,nan,'a',2,nan,nan] 唯一=设置(事物) 打印(唯一)#{0,1,2,nan,'a'} #测试2 things=[0,1,2,float('nan'),'a',1,float('nan'),'a',2,float('nan'),float('nan')] 唯一=设置(事物) 打印(唯一)#{0,1,2,nan,nan,nan,nan

我刚刚偶然发现了Python的这一有趣行为,它涉及
set
s中的
NaN

#测试1
nan=浮点('nan')
事物=[0,1,2,nan,'a',1,nan,'a',2,nan,nan]
唯一=设置(事物)
打印(唯一)#{0,1,2,nan,'a'}
#测试2
things=[0,1,2,float('nan'),'a',1,float('nan'),'a',2,float('nan'),float('nan')]
唯一=设置(事物)
打印(唯一)#{0,1,2,nan,nan,nan,nan,'a'}
同一个键
nan
在上一个
集合中多次出现
当然看起来很奇怪

我认为这是由于
nan
与自身不相等(定义为)以及在将对象添加到
集合时,在值相等之前根据内存位置(
id()
)对对象进行比较这一事实造成的。然后,每个
float('nan')
生成一个新对象,而不是返回一些全局“单例”
float
(如小整数)

  • 事实上,我只是发现描述同样的行为,似乎证实了上述
问题:

  • 这真的是你想要的行为吗
  • 假设我从上面得到了第二个
    东西。我如何计算实际唯一元素的数量?通常的
    len(set(things))
    显然不起作用。事实上,我可以使用
    导入numpy作为np;len(np.unique(things))
    ,但我想知道这是否可以在不使用第三方库的情况下实现
  • 补遗 作为一个小附录,让我补充一个类似的故事适用于
    dict
    s:

    d={float('nan'):0,float('nan'):1}
    打印(d){nan:0,nan:1}
    
    我的印象是,
    NaN
    dict
    s中是一个完全不允许使用的键,但只要存储对用作键的确切对象的引用,它实际上就会起作用:

    nan0=float('nan')
    nan1=浮点('nan')
    d={nan0:0,nan1:1}
    d[float('nan')]#键错误
    d[nan0]#0
    d[nan1]#1
    

    当然,这很有意思,但如果需要在现有的
    dict
    中存储额外的值,并且不关心要使用哪些键,当然每个新键都不必已经在
    dict
    中,我可以看到这个技巧很有用。也就是说,可以使用
    float('nan')
    作为一个工厂来生成无休止的新
    dict
    键,保证现有或将来的键不会相互碰撞。

    float()
    的期望行为是返回float(类)的实例。你说得对,“南”并不等于它本身。因此,
    float(1)==float(1)
    float('nan')!=浮点('nan')

    为了得到一个唯一的集合,我建议像在测试1中那样建立一个nan常量。如果这不适合你,你可以选择导入数学;math.isnan(float('nan'))
    。迭代列表(或集合)并删除元素。
    newlist=[x代表x,如果不是数学的话。isnan(x)]

    你可能会想:不,我删除所有的南。如果以前有一个呢

    import math
    
    things = [0, 1, 2, float('nan'), 'a', 1, float('nan'), 'a', 2, float('nan'), float('nan')]
    nan = float('nan')
    length = len(things)
    newlist = [ x for x in things if not isinstance(x, str) and not math.isnan(x) ]
    if len(newlist) != length:
        newlist.append(nan)  # or however you'd like to handle it
    unique = set(newlist)
    print(unique)
    

    {0,1,2,nan}

    对于nan问题,通常没有一刀切的解决方案。假设您有一些计算,如果使用真实数算法执行,可能会产生四种不同的结果,但由于浮点算法的限制,它会产生1,NaN,3,NaN。在这种情况下,关于结果集中有多少元素的理想答案是四个。因此,NAN应被视为不同的事物。另一方面,在其他一些计算中,理想结果可能是7,7,7,7,但计算结果是7,NaN,7,NaN。在这种情况下,…对于结果集中有多少个元素的理想答案应该是一个。因此,NAN应被视为相同的。但NaN的本质是,它不知道在理想情况下会是什么。因此,在没有其他信息的情况下,我们无法知道如何处理它。因此,您的数据中有NAN,处理它们主要是您的责任,不要期望库例程会为您处理它们。至于您的第一个问题,如果您使用
    class foo():pass,a=foo()
    并打印出
    b=[a,a]
    c=[foo(),foo()]的结果
    显示为
    b
    有两个地址相同的对象,而
    c
    显示两个不同的对象。我认为这与float()也是类对象有关?您也可以尝试
    set(b)
    set(c)
    ,结果与您的case@EricPostpischil公平,但是说我现在的处境是,我真的想把NaN的作为问题来对待。并非所有的NaN都是错误算法的结果,有些是故意作为占位符插入的。@jmd_dk使用None作为占位符,而不是NaN。另外,如果你能给出需要NaN作为占位符的例子,那将是很好的
    float(np.NaN)=float(np.NaN)
    给出类似
    float('NaN')==float('NaN')
    False,而
    things=[0,1,2,float(np.NaN),'a',1,float(np.NaN),'a',2,float(np.NaN)]
    给出了类似于测试1{,1,1,2,NaN,'a'}。为什么?@RuthgerRighart
    float(np.nan)
    总是返回同一个对象,
    float('nan')
    不返回。它总是返回一个新对象。运行
    float('nan')。\uuuu repr\uuuu
    两次,用
    np.nan