如何在Python中区分不同types的NaN float

我正在编写Python 2.6代码,通过Windows中的COM与NI TestStand 4.2进行交互。 我想为一个variables创build一个“NAN”值,但是如果我把它传递给float('nan') ,TestStand将它显示为IND

显然,TestStand区分浮点“IND”和“NAN”值。 根据TestStand的帮助 :

  • IND对应于Visual C ++中的Signaling NaN ,而
  • NAN对应于QuietNaN

这意味着Python的float('nan')实际上是通过COM传递的信号NaN 。 然而,从我所读到的有关NaN的信号来看,似乎NaN信号有点“异国情调”, 安静的NaN就是你的“常规”NaN。 所以我怀疑Python是否会通过COM传递一个Signaling NaN我怎么能find一个Python的float('nan')是否通过COM作为一个信号NaN安静的NaN ,或可能不确定

在与其他语言进行交互时,有什么办法可以让NaNQuietNaN或Python中的不确定 信号发生关系? (也许使用ctypes ?)我认为这将是一个特定于平台的解决scheme,我接受这种情况。

更新:在TestStand序列编辑器中,我尝试了两个variables,一个设置为NAN ,另一个设置为IND 。 然后我将它保存到一个文件。 然后我打开文件并使用Python读取每个variables。 在这两种情况下,Python都会将它们看作一个nan浮标。

我为你挖了一点,我想你可能会结合使用struct模块与凯文的汇总图表上的信息。 他们解释了用于各种IEEE 754浮点数的确切位模式。

如果我读了这个IND -eterminate值的主题,唯一可能需要小心的是,当直接用C代码赋值时,该值往往会触发某种浮点中断,导致它被转换为一个朴素的NaN。 这又意味着那些人被建议在ASM中做这种事情,而不是C,因为C把这些东西抽象掉了。既然这不是我的领域,而且我不确定这种价值会在多大程度上混淆Python,我想我会提到它,所以你至少可以留意任何这种怪异的行为。 (请参阅此问题的接受答案)。

 >>> 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。

让我们尝试制作一个Signaling 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' 

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

nan的CPython定义

当Python报告一个nan ,这是从哪里来的?

  • 计算结果(平台特定值?)
  • Py_NAN在CPython C源代码中
    • 定义为(Py_HUGE_VAL * 0.)
      • 价值是平台特定的
      • Py_HUGE_VAL可能被定义为HUGE_VAL – 它有一个说明它应该是HUGE_VAL除了那个被破坏的平台上。
  • 在CPython的C源代码中由Py_NAN定义的float('nan')

阅读Python和pywin32源代码

我看了一下pywin32的C源代码,特别是构成Python↔COM翻译层的win32com。 该代码:

  • 作为输入对象
  • 调用PyNumber_Float()将其转换为Python float (如果它尚未)
  • 调用PyFloat_AsDouble()将其转换为普通的C double值。
    • 这只是返回直接包含在PyFloatObject成员ob_fval的C double

所以看起来好像我已经从COM接口跟踪了一个NaN到一个包含Py_NAN的普通C double类型,无论结果是在Windows平台上。

TestStand NAN值

现在我已经用NI TestStand试了一下。 首先我尝试过:

 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) 

但是,这仍然出现在TestStand作为IND 。 于是我创建了一个变量设置为INDNAN的TestStand文件,并从Python读取值。 事实证明,TestStand的NAN值为FFFF000000000001 。 根据凯文的总结图是南宁。 TestStand的IND确实具有不确定的预期值, FFF8000000000000

成功

所以,毕竟,我已经成功地在Python中设置了TestStand中的NAN:

 # 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) 

约翰·库克在这方面有一个很好的帖子,可能会有所帮助:

  • Python中的IEEE浮点运算

更新 :不会工作吗?

 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