代码之家  ›  专栏  ›  技术社区  ›  Craig McQueen Dr. Watson

如何区分Python中不同类型的NaN float

  •  10
  • Craig McQueen Dr. Watson  · 技术社区  · 15 年前

    我正在编写与 NI TestStand 4.2通过Windows中的COM。我想为变量设置一个“NAN”值,但是如果我传递它 float('nan') ,TestStand显示为 IND .

    显然TestStand区分了浮点“IND”和“NAN”值。根据 TestStand help :

    • 工业 对应于 信号NaN 在Visual C++中,同时
    • NAN 对应于 安静的

    这意味着Python的 浮动('nan') 实际上是 信号NaN 当通过COM时。不过,据我所知 信号NaN ,看起来 信号NaN 有点“异国情调”而且 静楠 是你的“常客”奶奶。所以我怀疑Python是否会 信号NaN 通过COM。 我怎么知道一条蟒蛇 浮动('nan') 通过COM作为 信号NaN 静楠 ,或者 不确定 ?

    有没有什么办法 信号NaN 安静的 不确定 在Python中,当与其他语言交互时?(使用 ctypes 也许吧?)我假设这是一个特定于平台的解决方案,在这种情况下我会接受。

    更新: 在TestStand序列编辑器中,我尝试创建两个变量,一个设置为 另一个设置为 工业 . 然后我把它存到一个文件里。然后我打开文件,使用Python读取每个变量。在这两种情况下,Python都将它们作为 nan 漂浮。

    4 回复  |  直到 15 年前
        1
  •  8
  •   Community Mohan Dere    8 年前

    我给你挖了点,我想你可以用 struct 模块与at上的信息相结合 Kevin's Summary Charts . 它们解释了各种IEEE 754浮点数使用的确切位模式。

    如果我读到关于这个的话题,你可能唯一需要注意的就是 IND -确定值,是指在C代码中直接赋值时,该值倾向于触发某种浮点中断,导致它变成一个普通的NaN。这反过来意味着这些人被建议用ASM而不是C来做这种事情,因为C把这些东西抽象了出来。。因为它不是我的领域,而且我不确定这种值会在多大程度上影响Python,所以我想我应该提到它,这样你至少可以留意到任何这样奇怪的行为。(见接受的答案 this question ).

    >>> import struct
    
    >>> struct.pack(">d", float('nan')).encode("hex_codec")
    'fff8000000000000'
    
    >>> import scipy
    >>> struct.pack(">d", scipy.nan).encode("hex_codec")
    '7ff8000000000000'
    

    凯文总结图表 ,这表明 float('nan') 实际上是不确定的值,而 scipy.nan 是一个安静的南。

    让我们试着制作一个信号NaN,然后验证它。

    >>> try_signaling_nan = struct.unpack(">d", "\x7f\xf0\x00\x00\x00\x00\x00\x01")[0]
    >>> struct.pack(">d", try_signaling_nan).encode("hex_codec")
    '7ff8000000000001'
    

    不,信号NaN被转换成一个安静的NaN。

    现在让我们试着直接做一个安静的NaN,然后验证它。

    >>> try_quiet_nan = struct.unpack(">d", "\x7f\xf8\x00\x00\x00\x00\x00\x00")[0]
    >>> struct.pack(">d", try_quiet_nan).encode("hex_codec")
    '7ff8000000000000'
    

    所以这就是如何使一个适当的安静南使用 struct.unpack() --至少,在Windows平台上。

        2
  •  4
  •   Craig McQueen Dr. Watson    15 年前

    CPython对nan的定义

    当Python报告 nan ,那是从哪里来的?

    • 计算结果(平台特定值?)
    • Py_NAN 在CPython C源代码中
      • 定义为 (Py_HUGE_VAL * 0.)
        • 价值是特定于平台的
        • Py_HUGE_VAL 可能被定义为 HUGE_VAL --它有一张纸条说它应该是 巨大的 除非是在平台上。
    • float('nan') 定义自 皮尤南 在CPython的C源代码中。

    阅读Python和pywin32源代码

    我已经看过了 pywin32 ,尤其是 win32com ,它形成了Python–COM转换层。密码是:

    • 获取输入对象
    • 电话 PyNumber_Float() 将其转换为Python float (如果还没有)
    • 电话 PyFloat_AsDouble() 将其转换为纯C double 价值。
      • 这只是返回C 双重的 直接包含在 PyFloatObject 成员 ob_fval .

    看来我已经追踪到 NaN 从COM接口返回到纯C 双重的 类型包含 皮尤南 ,无论是在Windows平台上。

    试验台NAN值

    现在我已经在NI测试台上试过了。首先我试着:

    quiet_nan = struct.unpack(">d", "\x7f\xf8\x00\x00\x00\x00\x00\x01")[0]
    # Set the variable's value in TestStand
    locals_prop_object.SetValNumber(var_name, 0, quiet_nan)
    

    但在测试台上仍然显示为 IND . 所以我创建了一个TestStand文件,变量设置为 工业 NAN ,并从Python中读取值。原来那个试验台 值为 FFFF000000000001 . 根据 Kevin's Summary Charts 那是一个 消极的 安静的南。试验台 工业 是否具有的预期值 不确定 , FFF8000000000000 .

    成功

    所以,毕竟,我在TestStand中成功地设置了一个NAN,来自Python:

    # Make a NAN suitable for TestStand
    teststand_nan = struct.unpack(">d", "\xff\xff\x00\x00\x00\x00\x00\x01")[0]
    # Set the variable's value in TestStand
    locals_prop_object.SetValNumber(var_name, 0, teststand_nan)
    
        3
  •  2
  •   ars    15 年前

    John Cook在这方面有一篇很好的文章可能会有帮助:

    更新 :这不管用吗?

    In [144]: import scipy
    
    In [145]: scipy.nan
    Out[145]: 1.#QNAN
    
    In [146]: scipy.inf
    Out[146]: 1.#INF
    
    In [147]: scipy.inf * 0
    Out[147]: -1.#IND
    
        4
  •  0
  •   HackerBoss    7 年前

    据我所知,似乎有一些困惑,认为 NaN 决定是否安静。相反,惯例是尾数中最重要的一点决定了这一点。从 Wikipedia (重点补充):

    在IEEE 754标准一致的浮点存储格式中,nan由NaNs特有的特定的、预定义的位模式来标识。 符号位无关紧要 . 二进制格式的nan由充满一个的指数字段(如无穷大值)和有效位字段中的一些非零数(使它们与无穷大值不同)表示。1985年的原始IEEE 754标准(ieee754-1985)只描述了二进制浮点格式,没有说明如何标记信令/安静状态。在实际应用中,有效位字段的最高有效位决定了NaN是在发信号还是在静音。。。2008年修订的IEEE 754标准(ieee754-2008)对信令/静默状态的编码提出了正式建议。 对于二进制格式,有效位字段的最有效位应该是“is_quiet”标志。一、 e.如果NaN是安静的,则该位为非零;如果NaN是信令,则该位为零 .

    因为大多数实现都符合IEEE 754-2008,所以这是您应该遵循的约定。一般来说,您不能计划在标记位上为nan保持一致,即使在同一平台上为不同的nan也是如此。根据本公约, float('nan') scipy.nan 两人似乎都是安静的奶奶,至少在上面讨论的情况下是这样。